Python 3:优化项目Euler问题#14
我正在尝试使用Python3解决(最长的Collatz序列)。下面是我的实现Python 3:优化项目Euler问题#14,python,python-3.x,memoization,collatz,Python,Python 3.x,Memoization,Collatz,我正在尝试使用Python3解决(最长的Collatz序列)。下面是我的实现 cache_limit = 5000001 lookup = [0] * cache_limit lookup[1] = 1 def collatz(num): if num == 1: return 1 elif num % 2 == 0: return num >> 1 else: return (3 * num) + 1
cache_limit = 5000001
lookup = [0] * cache_limit
lookup[1] = 1
def collatz(num):
if num == 1:
return 1
elif num % 2 == 0:
return num >> 1
else:
return (3 * num) + 1
def compute(start):
global cache_limit
global lookup
cur = start
count = 1
while cur > 1:
count += 1
if cur < cache_limit:
retrieved_count = lookup[cur]
if retrieved_count > 0:
count = count + retrieved_count - 2
break
else:
cur = collatz(cur)
else:
cur = collatz(cur)
if start < cache_limit:
lookup[start] = count
return count
def main(tc):
test_cases = [int(input()) for _ in range(tc)]
bound = max(test_cases)
results = [0] * (bound + 1)
start = 1
maxCount = 1
for i in range(1, bound + 1):
count = compute(i)
if count >= maxCount:
maxCount = count
start = i
results[i] = start
for tc in test_cases:
print(results[tc])
if __name__ == "__main__":
tc = int(input())
main(tc)
我现在被这件事困扰了一段时间。不知道这里还能做些什么
这里还有什么可以优化的,这样我就不会超时了
任何帮助都将不胜感激:)
注意:使用上述实现,我能够解决实际的Project Euler问题#14。它只为hackerrank中的4个测试用例提供超时时间。以下是我的实现(专门针对Project Euler网站上的问题):
num=1
limit=int(输入())
seq_list=[]
而num<限制:
序列号=0
n=num
如果n==1:
顺序_num=1
其他:
而n!=1:
如果n%2==0:
n=n/2
序列号_num+=1
其他:
n=3*n+1
序列号_num+=1
序列号_num+=1
序号列表追加(序号)
num+=1
k=序列列表索引(最大值(序列列表))
打印(k+1)
是的,您可以对代码做一些事情来优化它。但我认为,更重要的是,有一个数学观察需要考虑,这是问题的核心:
whenever n is odd, then 3 * n + 1 is always even.
有鉴于此,我们总是可以将(3*n+1)除以2。这为我们节省了不少时间……这里有一个改进(需要1.6秒):不需要计算每个数字的顺序。您可以创建字典并存储序列中元素的数量。如果出现的数字已经出现,则序列计算为dic[原始编号]=dic[n]+计数-1。这节省了很多时间
import time
start = time.time()
def main(n,dic):
'''Counts the elements of the sequence starting at n and finishing at 1'''
count = 1
original_number = n
while True:
if n < original_number:
dic[original_number] = dic[n] + count - 1 #-1 because when n < original_number, n is counted twice otherwise
break
if n == 1:
dic[original_number] = count
break
if (n % 2 == 0):
n = n/2
else:
n = 3*n + 1
count += 1
return dic
limit = 10**6
dic = {n:0 for n in range(1,limit+1)}
if __name__ == '__main__':
n = 1
while n < limit:
dic=main(n,dic)
n += 1
print('Longest chain: ', max(dic.values()))
print('Number that gives the longest chain: ', max(dic, key=dic.get))
end = time.time()
print('Time taken:', end-start)
导入时间
开始=时间。时间()
def总管(n,驾驶员信息中心):
''计算从n开始到1结束的序列元素''
计数=1
原始编号=n
尽管如此:
如果n<原始编号:
dic[原始编号]=dic[n]+计数-1#-1,因为当n<原始编号时,n会计数两次,否则
打破
如果n==1:
dic[原始编号]=计数
打破
如果(n%2==0):
n=n/2
其他:
n=3*n+1
计数+=1
返回dic
限值=10**6
dic={n:0表示范围(1,极限+1)}
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
n=1
当n<极限时:
dic=主(n,dic)
n+=1
打印('最长链:',最大值(dic.values()))
打印('给出最长链的编号:',max(dic,key=dic.get))
end=time.time()
打印('所用时间:',结束-开始)
解决这个问题的诀窍是只计算最大输入的答案,并将结果保存为查找所有较小输入,而不是计算极值上限
这是我的实现,它通过了所有测试用例
MAX=int(5*1e6)
ans=[0]
步骤=[0]*(最大值+1)
def解算(N):
如果N>1)#这是递归
如果N=mx:
mx=当前计数
collatz=i
附加说明(collatz)
对于uu输入:
打印(ans[3;])
感谢您的回答,但我正在寻找关于我的实现不起作用的原因的解释。此外,就实际的project Euler问题的解决方案而言,上述实现已经起到了作用。在许多hackerrank的问题中,如果您使用python,就会出现该错误。与其他语言中的代码完全相同,它将通过所有测试。@rpanai-Hmm。。。看起来像是。。。
import time
start = time.time()
def main(n,dic):
'''Counts the elements of the sequence starting at n and finishing at 1'''
count = 1
original_number = n
while True:
if n < original_number:
dic[original_number] = dic[n] + count - 1 #-1 because when n < original_number, n is counted twice otherwise
break
if n == 1:
dic[original_number] = count
break
if (n % 2 == 0):
n = n/2
else:
n = 3*n + 1
count += 1
return dic
limit = 10**6
dic = {n:0 for n in range(1,limit+1)}
if __name__ == '__main__':
n = 1
while n < limit:
dic=main(n,dic)
n += 1
print('Longest chain: ', max(dic.values()))
print('Number that gives the longest chain: ', max(dic, key=dic.get))
end = time.time()
print('Time taken:', end-start)
MAX = int(5 * 1e6)
ans = [0]
steps = [0]*(MAX+1)
def solve(N):
if N < MAX+1:
if steps[N] != 0:
return steps[N]
if N == 1:
return 0
else:
if N % 2 != 0:
result = 1+ solve(3*N + 1) # This is recursion
else:
result = 1 + solve(N>>1) # This is recursion
if N < MAX+1:
steps[N]=result # This is memoization
return result
inputs = [int(input()) for _ in range(int(input()))]
largest = max(inputs)
mx = 0
collatz=1
for i in range(1,largest+1):
curr_count=solve(i)
if curr_count >= mx:
mx = curr_count
collatz = i
ans.append(collatz)
for _ in inputs:
print(ans[_])