我不明白这两个代码有什么不同,因为它们执行或多或少的相同操作,但是我增加的越多,两个代码之间的时间差就越大。这两个代码的Big O相同,因为第一个代码中的while循环与第二个代码中的for循环具有相同的目的,第一个代码中的嵌套for循环与第二个嵌套的while循环扫描所有元素一样。如果是这样,怎么可能? (这两个代码是外观序列的实现:https://en.wikipedia.org/wiki/Look-and-say_sequence)
import time
a = time.time()
def look_and_say_sequence(first_element, n):
while n != 1 :
next_element , start , k = '' , first_element[0] , 0
for x in first_element :
if x != start :
next_element , start , k = next_element + str(k) + start , x , 1
else :
k = k + 1
first_element = next_element + str(k) + start
n = n - 1
return first_element
look_and_say_sequence('1', 48)
b = time.time()
print(b-a) # 10 SECONDS
#########################################################################################`
a = time.time()
def look_and_say_sequence(first, n):
result = first
for _ in range(n-1):
sequence = result
result = ''
index = 0
while index < len(sequence):
pending = sequence[index]
count = 0
while index < len(sequence) and pending == sequence[index]:
count += 1
index += 1
result += "{}{}".format(count, pending)
return result
look_and_say_sequence('1', 48)
b = time.time()
print(b-a) # 2 SECONDS
谢谢您的帮助!
答案 0 :(得分:1)
您的速度变慢了
next_element , start , k = next_element + str(k) + start , x , 1
,当next_element是一个非常长的字符串时,这会导致大量的运行时损失(随着n的增大,这种情况肯定会发生-next_element的长度超过500k个字符,n = 48)。尝试运行以下两个脚本:
import time
a = time.time()
s = ''
for i in range(99999):
s = (s + '1') + '1' # comment this out
# s += '1' + '1' # and uncomment this to see the speed difference
b = time.time()
print(b-a)
您会发现使用+ =可以更快地运行。 Python从左到右求值,这意味着(s + '1')
必须在附加+ '1'
之前求出新字符串。这就是增加这么多减速的原因。
如果将问题行更改为
,则继续next_element += str(k) + start
start = x
k = 1
您实际上会看到顶级算法运行得更快