我一直在研究Euler project problem 4,我的代码运行正常,但需要花费太多时间(0.41秒)。我如何优化它以便花费更少的时间。我有一个技巧我是遗失,或者我不知道的特殊功能?
这是代码:
#Note: tpal is a function to test if number is palindrome
pal =0
for i in range(999,100,-1):
if pal >= i*999: #A way to get out of loop and to not test on all numbers
break
for j in range(999,100,-1):
if pal >= i*999:
break
if j > i: #numbers would already have been tested so I skip them
continue
pot=i*j
if ((tpal(pot)==1)and(pot> pal)):
pal=pot
i1=i
j1=j
print(i1,j1,pal)
def tpal(num):
num=list(str(num))
Le=len(num)
if Le == 1: # if number is of one digit than palindrome
return 1
le=len(num)
if le%2 !=0: #4 example 10101even nbr
le-=1
le/2
for i in range(0,le):
if num[i]!=num[Le-i-1]:
return 0
return 1
答案 0 :(得分:2)
现在事实证明代码已经< 1 s运行时,它不再那么有趣了。您可以修改代码以测试更少的数字并尽快放弃。但有一个明显的优化,有点可爱。这一行:
if ((tpal(pot)==1)and(pot> pal)):
每次检查是否有什么是回文,即使是pot <= pal
。回文试验很昂贵。如果你只是交换订单:(注意你不需要==1
):
if (pot > pal) and tpal(pot):
那么你可以节省很多时间:
In [24]: timeit orig()
1 loops, best of 3: 201 ms per loop
In [25]: timeit orig_swapped()
10 loops, best of 3: 30.1 ms per loop
因为如果A and B
已经为假,A
不评估B,因此它知道A and B
必须为false。 (这称为“短路”;如果A
为真,则“A或B”也会发生同样的情况。)
顺便提一下,最后一行在这里:
if le%2 !=0: #4 example 10101even nbr
le-=1
le/2
^^^^
不会更改le
。我认为这三行意味着le //= 2
。
答案 1 :(得分:1)
试试这个,它不应该花费长达31秒的时间:
def isPalindrome(n):
return str(n) == str(n)[::-1]
def listNums():
a, b, pal = 0, 0, 0;
for i in range(999, 99, -1):
for j in range(999, 99, -1):
n = i * j
if isPalindrome(n) and n > pal: # better to use "n > pal and isPalindrome(n)" instead, see other answer for details.
a, b, pal = i, j, n
return a, b, pal
print listNums()
运行此操作大约需要1秒钟。对于这样的事情你肯定不需要循环中那些多余的if
语句 - 如果你循环,比如说,range(9999, 999, -1)
,你可能会考虑进行一些这样的优化(当然,有一个可以对这样的事情进行多种潜在的优化,例如,不能遍历每个i,j对两次)。
答案 2 :(得分:0)
没有给你完整的答案。这是一些指针。
i
开始? int(str(pot)[::-1])==pot
然后是它的回文编辑: 让男/女解决他/她自己的问题。无需在此处发布解决方案。