0

我一直在研究 Project Euler 问题 4。我是 java 新手,相信我已经找到了答案(906609 = 993 * 913,通过使用 Excel!)。

当我打印注释掉的行时,我可以知道我的字符串操作已经奏效。我已经研究了几种比较字符串的方法,以防我没有理解某些东西,但是这个例程并没有给我结果。

请帮我确定为什么它不打印答案?

詹姆士

public class pall{
    public static void main(String[] args){

    int i;
    int j;
    long k;
    String stringProd;

    for(i=994;i>992; i--){
        for (j=914;j>912; j--){
            k=(i*j);
            stringProd=String.valueOf(k);
            int len=stringProd.length();

            char[] forwards=new char[len];
            char[] back = new char[len];

            for(int l=0; l<len; l++){
                forwards[l]=stringProd.charAt(l);
            }

            for(int m=0; m<len;m++){
                back[m]=forwards[len-1-m];

            } 

            //System.out.println(forwards);
            //System.out.println(back);

            if(forwards.toString().equals(back.toString())){
                System.out.println(k);}
            }
        }
    }
}
4

2 回答 2

8

您正在比较数组的字符串表示形式。toString()没有给你你的想法。例如,下面的代码清楚地表明:

char[] arr1 = {'a', 'b'};
char[] arr2 = {'a', 'b'};

System.out.println(arr1.toString() + " : " + arr2.toString());

此代码打印:

[C@16f0472 : [C@18d107f

因此,两个数组的字符串表示形式不同,即使内容相同。这是因为数组不会覆盖toString()方法。它继承了Object#toString()方法。

class的toString方法Object返回一个字符串,该字符串由对象作为实例的类的名称、at 符号字符@和对象哈希码的无符号十六进制表示形式组成。换句话说,此方法返回一个等于以下值的字符串:

getClass().getName() + '@' + Integer.toHexString(hashCode())

所以,在上面的输出中,[C是 的输出char[].class.getName()18d107f是哈希码。

您也不能使用 比较数组forward.equals(back),因为 Java 中的数组不会覆盖equals()hashCode()两者之一。有什么选择吗?是的,为了比较数组,您可以使用Arrays#equals(char[], char[])方法:

if (Arrays.equals(forward, back)) {
    System.out.println(k);
}

此外,要获取您的char数组,您不需要这些循环。你可以使用String#toCharArray()方法。并且为了得到字符串的反转,你可以将字符串包装在一个StringBuilder实例中,并使用它的reverse()方法:

char[] forwards = stringProd.toCharArray();
char[] back = new StringBuilder(stringPod).reverse().toString().toCharArray();

既然你已经找到了一种简单的方法来反转一个字符串,那么String#equals()直接使用方法如何,而不是创建那些字符数组呢?

String stringPod = String.valueOf(k);
String reverseStringPod = new StringBuilder(stringPod).reverse().toString()

if (stringPod.equals(reverseStringPod)) {
    System.out.println(k);
}

最后,因为它是关于欧拉项目,它是关于速度,主要是数学。您应该考虑避免String使用实用程序,并使用一般除法和模数算术,从头到尾获取每个单独的数字,并比较它们。

于 2013-09-24T10:22:12.813 回答
2

将字符串转换为char[]使用

char[] forward = stringProd.toCharArray();

要将 a 转换char[]String,请使用String(char[])构造函数:

String backStr = new String(back); // Not the same as back.toString()

但是,这不是最高效的解决方案,原因如下:

  • 您不需要构造一个back数组来检查一个字符串是否是回文- 您可以从两端遍历字符串,边走边比较字符,直到您发现差异或您的索引在中间相遇。
  • 您可以重复使用相同的数组,而不是在循环中构造一个新数组- 如果您确实想继续使用数组,您可以将它分配一次以获得 product 的最大长度k,并在循环的所有迭代中使用它.
  • 您不需要将数字转换为字符串来检查它是否是回文- 您可以通过重复除以 10 的余数得到它的数字,然后除以 10 到下一个数字。

这是最后一点的说明:

boolean isPalindrome(int n) {
    int[] digits = new int[10];
    if (n < 0) n = -n;
    int len = 0;
    while (n != 0) {
        digits[len++] = n % 10;
        n /= 10;
    }
    // Start two indexes from the opposite sides
    int left = 0, right = len-1;
    // Loop until they meet in the middle
    while (left < right) {
        if (digits[left++] != digits[right--]) {
            return false;
        }
    }
    return true;
}
于 2013-09-24T10:37:22.540 回答