找到两个3位数的最大回文产品:逻辑中的错误是什么?

时间:2014-09-19 13:08:25

标签: python algorithm palindrome

我想通过以下方式解决这个问题:从两个变量值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.你能指出我逻辑不正确的地方吗?

2 个答案:

答案 0 :(得分:2)

以下是一些提示:

  1. 如果n = y * x是范围(600000,700000)中的任何数字(例如),其中y <= x且x <1000,则x的最小可能值是多少?
  2. 如果n是回文编号,则其第一个和最后一个数字都是6,那么这对x&amp;的最后一位数意味着什么呢? Y'
  3. 现在概括并找出一种有效的算法。 :)

    我以前从来没有做过这个问题,但我只编写了一个相当快的算法,比使用

    的蛮力搜索快了大约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]范围内两个数的因子的分割是微不足道的。