我想通过以下方式解决这个问题:从两个变量值999开始,在一个循环中相互相乘,减少一个或另一个,直到找到回文。代码是这样的:
def is_palindrome(n):
if str(n) == str(n)[::-1]:
return True
else:
return False
def largest_palindrome_product_of_3_digit():
x = 999
y = 999
for i in reversed(range(x + y + 1)):
if is_palindrome(x * y):
return x * y
if i % 2 == 0:
x -= 1
else:
y -= 1
我的方法的结果是698896,而正确的结果是906609.你能指出我逻辑不正确的地方吗?
答案 0 :(得分:2)
以下是一些提示:
现在概括并找出一种有效的算法。 :)
我以前从来没有做过这个问题,但我只编写了一个相当快的算法,比使用
的蛮力搜索快了大约2000倍for x in xrange(2, 1000):
for y in xrange(2, x+1):
n = y*x
#etc
根据timeit.py,我的旧机器上的暴力算法大约需要1.29秒,我上面提到的算法大约需要747微秒。
修改强>
我已经改进了界限(稍微修改了我的算法)并将时间缩短到410微秒。 :)
在评论中回答您的问题:
是的,我们可以在范围开头的平方根处开始x,我们可以在x处停止y(以防我们找到一个回文方块)。
我得到的第二个提示是,对于x = 10 * I + i,y = 10 * J + j,我们不需要测试i和j的所有81种组合,我们只需要测试其中(i * j)%10等于我们想要的数字的那些。因此,如果我们知道我们的回文以9开始和结束,则(i,j)必须在[(1,9),(3,3),(7,7),(9,1)]中。
我认为我不应该在这里发布我的实际代码;在SO上发布完整的解决方案来解决项目欧拉问题被认为是糟糕的形式。当人们提供暗示时,也许有些SO人甚至不喜欢它。也许这就是我投票的原因......
答案 1 :(得分:0)
你错过了可能的数字。
您正在考虑O(x + y)数字,您需要考虑O(x * y)数字。你的选择基本上是将其中一个从999循环到1,然后再递减另一个......
简单演示:
>>> want = set()
>>> for x in [1, 2, 3, 4, 5]:
... for y in [1, 2, 3, 4, 5]:
... want.add(x * y)
...
>>> got = set()
>>> x = 5
>>> y = 5
>>> for i in reversed(range(x + y + 1)):
... got.add(x * y)
... if i % 2:
... x -= 1
... else:
... y -= 1
...
>>> want == got
False
或者,您确实知道范围的顶部(999 * 999)并且您可以生成该范围内的所有回文数字,从最高到最低。从那里开始,进行素数分解并检查是否存在乘以[100,999]范围内两个数的因子的分割是微不足道的。