从两位三位数的乘积优化最大回文?

时间:2015-04-29 01:34:37

标签: java algorithm optimization palindrome

我正在处理一个面试问题,我被问到我应该编写一个程序,从两位三位数的产品中找到最大的回文。

以下是question

我想出了这种从底部开始的蛮力方法。

public class LargestPalindromeQuestion {

    public static void main(String[] args) {
        int value = 0;
        for (int i = 100; i <= 999; i++) {
            for (int j = i; j <= 999; j++) {
                int value1 = i * j;
                if (isPalindrome(value1) && value < value1) {
                    value = value1;
                }
            }
        }
        System.out.println(value);
    }

    private static boolean isPalindrome(final int product) {
        int p = product;
        int reverse = 0;
        while (p != 0) {
            reverse *= 10;
            reverse += p % 10;
            p /= 10;
        }
        return reverse == product;
    }
}

他们问我在这个计划中可以做些什么?我提到我们可以尝试修剪搜索空间并优化搜索空间中每个项目的检查步骤,但后来我很困惑如何在上面的解决方案中完成这项工作?

我们可以在此计划中进行哪些优化?现在它正在执行810000步骤以找到最大的回文。

我们可以通过两个三位数找到最大回文的最小步数是多少?

4 个答案:

答案 0 :(得分:4)

该程序对我来说非常好。我会将i循环计数从999降低到100,我只会检查j值,这些值实际上会产生比当前最大值更大的产品。

这个程序很快就能以i == 952精确地完成。这样做的数学原因是,一旦找到解906609993 * 913),就不可能找到更大的回文,其中较大的因子小于{{的平方根。 1}},即906609

952.160...

答案 1 :(得分:1)

一种非常简单的优化方法是简单地从最高的3位数而不是最小的数字开始。由于解决方案很可能更接近于对(999,999)而不是(100,100)。

答案 2 :(得分:1)

修剪搜索树的一个有用机制是注意到产品a = 111; b = 112 a*b = 12432 ; b = 113 a*b = 12543 ; b = 114 a*b = 12654 ; ... ; b = 180 a*b = 19980 ; b = 181 a*b = 20091 = (19980 + a) 的最高位数不会经常变化。 E.g。

 e.g.
 LSB = 1    --> a % 10 == 1, b % 10 == 1
            OR  a % 10 == 3, b % 10 == 7
            OR  a % 10 == 7, b % 10 == 3
            OR  a % 10 == 9, b % 10 == 9

因此,对于它们之间的所有值(a = 111,a&lt; b&lt; 181),已经知道MSB,其必须等于LSB或(a%10)*(b%10)% 10 == MSB。

{{1}}

大部分时间都没有,或者只有一个候选人在'b'中被检查任何一对MSB,一个%10。

答案 3 :(得分:0)

首先通过将6位数分成3位来优化isPalindrome。即N = ABCDEF =&gt; a = ABC = N / 1000,b = DEF = N%1000;然后反转b并返回== reversed_b;

其次,在生成回收物时,直到max_palindrome_so_far / 999为止,这是你要使用的最小值。 max_palindrome_so_far最初等于N。

public class Solution {

    public static boolean isPalindrome(int n){
        int a = n/1000;
        int b = n%1000;
        int d, r = 0, i = 3;
        while(i-- > 0){
            d = b%10;
            r = r*10 + d;
            b = b/10;
        }
        if (a == r)
            return true;
        return false;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t = in.nextInt();
        for(int a0 = 0; a0 < t; a0++){
            int n = in.nextInt();
            int r=0, m=n;
            int i,j;
            for(i = 999;i>=100;i--){
                for(j = 999;j>=m/999;j--){
                    if (i*j < n && i*j > 100000 && isPalindrome(i*j)){
                        r = Math.max(i*j, r);
                        m = r;
                    }
                }
            }

           // System.out.println(i + " * " + j + " = " + i*j);

            System.out.println(r);
        }
    }
}