因此,我正在研究具有1000万个键的字典,我的任务是让它在3秒钟内(在Intel 2.4 GHz上)工作。我尝试对代码进行性能分析,而while循环有很多成功之处,但是我想不出一种方法来使我的代码在没有它的情况下运行得更快。有没有一种方法可以改善我的代码以使其更快地工作?
该代码应该(并且这样做,但是太慢)创建一个字典,其中的键都是从2到999999的整数,并且值是由序列模式制成的列表的长度。模式是:如果整数是偶数,则将其除以2,如果整数是奇数且大于1,则将其乘以3并加1。这一直持续到达到数字1。
示例:3-> 10-> 5-> 16-> 8-> 4-> 2->1。此列表的长度是8。
代码:
import time
start = time.clock()
first = 2
last = 1000000
def function1(n,d):
if n/2 in d:
d[n] = d[n/2] + 1
if n not in d:
d[n] = 0
temp = n
while temp > 1:
if temp%2 == 0:
temp /= 2
d[n] += 1
else:
temp = 3*temp + 1
d[n] += 1
if temp in d:
d[n] += d[temp]
break
return d[n]
d={}
d[1]=1
d={key: function1(key,d) for key in range(first,last)}
print(time.clock() - start)
在我的系统上,您的代码确实耗时超过3秒(在最近的2.3 GHz Intel Core i7 Macbook Pro上使用Python 3.4)。
我可以通过使用局部变量并避免两次构建字典,在3秒内(减少至2.65秒,减少12%)得到它:
def function1(n,d):
if n/2 in d:
d[n] = d[n/2] + 1
return
if n not in d:
length = 0
temp = n
while temp > 1:
if temp%2 == 0:
temp //= 2
else:
temp = 3*temp + 1
length += 1
if temp in d:
length += d[temp]
break
d[n] = length
d={1: 1}
for key in range(first,last):
function1(key, d)
请注意,我使用局部length
变量,而不是一直读取长度d[n]
。Python中的局部变量存储在C数组中,从而避免了必须对键进行哈希处理并进行查找(可能包括哈希冲突)的情况。
我从/
(浮点除法)切换为//
(整数除法); 当您感兴趣的只是整数结果时,无需处理小数点。
如果在字典中找到,我也会返回n/2
。n not in d
测试成功没有意义,因为我们刚刚添加d[n]
了测试。
词典理解是完全多余的,function1()
已经d
就地更改,因此构建新词典来替换现有结果毫无意义。
下一步是利用temp
您刚刚计算的值序列。一开始,3
您需要计算其他几个值。所有这些都可以存储在d
一旦你完成,所以你不必重新计算序列10
,5
,16
,8
和4
两种:
def function1(n,d):
if n not in d:
length = 0
seen = []
while n > 1:
seen.append(n)
if n % 2 == 0:
n //= 2
else:
n = 3 * n + 1
length += 1
if n in d:
length += d[n]
break
for num in seen:
d[num] = length
length -= 1
这3
需要8个步骤,但是我们可以存储7个10
,6个5
等。
我if n/2 in d
完全放弃了测试,while
循环已经解决了这种情况。由于n
在该if n not in d
区块中不再需要该标记,因此我temp
完全放弃了,然后继续n
。
现在整个测试仅需1.75秒。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句