在char []中搜索char并使用String.indexOf()方法搜索String有什么区别?

时间:2017-10-16 04:17:09

标签: java string char

private static int getTotalWordValue(String word) {
    int totalWordValue = 0;

    // Code that produces correct results.
    for(int i=0; i < alpha.length(); i++) {
        char letter = alpha.charAt(i);
        for(char ch: word.toCharArray()) {
            if(letter == ch) {
                totalWordValue += i+1;
            }
        }
    }

    // Code that produces incorrect results.
    totalWordValue = 0;
    for(int i=0; i < alpha.length(); i++) {
        String letter = String.valueOf(alpha.charAt(i)); // <-- here?
        if(word.indexOf(letter) != -1) {
            totalWordValue += i+1;
        }
    }

    return totalWordValue;
}

运行上面的代码来解决Project Euler Problem 42后,我得到了不同的结果。上面显示的第一个'for'循环输出正确的结果,第二个'for'循环输出错误的结果。

上面的代码采用String并返回其单词值。例如,单词SKY将返回单词值55,因为此单词中的字母添加如下(从1开始):

  • S = 19(字母表的第19位)
  • K = 11(字母表的第11位)
  • Y = 25(字母表的第25位)。

19 + 11 + 25 = 55。

我已将问题减少到上面的代码,并且不明白为什么会发生这种情况。也许我错过了与Java String类及其方法相关的重要信息。

我在Windows 10上的Eclipse Neon.3发行版(4.6.3)中运行Java 8。

4 个答案:

答案 0 :(得分:1)

这两段代码完全不同。

在这两种情况下,你都有一个外部循环,用于提供变量alpha中字符串letter的每个字符。

在第一种情况下,您有一个内部循环,它贯穿字符串word每个字符,并计算每个匹配事件{{1 }}。当内部循环在letter中计算 {/ 1}}的每次时,外部循环将移至下一个letter

在第二种情况下,没有内循环。每次围绕外部循环,您都会使用word来查找letterword.indexOf(letter)第一次出现的索引。如果有,你提前计算。无论哪种方式,您现在已完成letter,外部循环移至下一个word。在letter中可能会出现letter的其他情况,但这种情况并未尝试查找并计算它们。

答案 1 :(得分:1)

对于包含多个字母多次的单词,第二个实现中的单词值不正确。例如对于WOOD, 第一种方法将计算3 + 14 + 14 + 22,但第二种方法将计算3 + 14 + 22。

为什么呢?第一种方法迭代 word 的字符:

for(char ch: word.toCharArray()) {
    if(letter == ch) {
        totalWordValue += i+1;
    }
}

第二种方法迭代字母的字符:

for(int i=0; i < alpha.length(); i++) {
    String letter = String.valueOf(alpha.charAt(i)); // <-- here?
    if(word.indexOf(letter) != -1) {
        totalWordValue += i+1;
    }
}

所以在&#34; WOOD&#34;的例子中, &#34; O&#34;只计算一次,而不是两次。

顺便说一下, 转换为String在这里毫无意义:

String letter = String.valueOf(alpha.charAt(i));
if(word.indexOf(letter) != -1) {

写出相同内容的更好方法:

char letter = alpha.charAt(i);
if (word.indexOf(letter) != -1) {

(但实施仍然不正确。)

最后, 如果字母表是英文A-Z,则可以更快地实现:

int totalWordValue = 0;
for (char c : word.toCharArray()) {
  if ('A' <= c && c <= 'Z') {
    totalWordValue += (c - 'A') + 1;
  }
}

return totalWordValue;

答案 2 :(得分:0)

indexOf 有4个重载方法,其中一个除了if let userUID = Auth().auth.currentUser?.uid{ ref.child("members/\(userUID)").setValue(*YOURMEMBERINFODICTIONARY*) } 参数,并返回字符序列中第一次出现的字符的索引。

现在,来找你问题。在您的方案中,characterindexOf的行为相同,因为您只传递了角色。而且,从内部开始,但是,想象一下,你有一个charAt并且你想检查并从另一个长String获取它的索引。那你会怎么做?来String

答案 3 :(得分:0)

我知道这并不一定能解决你提到的方法之间存在差异的问题,但其他人已经对此做出了很好的回答。

你想要字母表中字母的位置总和吗?我们可以在一个循环中使用一些算术来做到这一点,而不会增加内部循环或alpha常量的开销。

像这样:

public static int getWordValue(String word) {
    int value = 0; //total word value
    for(char c : word.toLowerCase().toCharArray()) { //iterate over character array of lower case string
            int charAsInt = (int) c; //cast char to int, giving the ASCII value
            if(charAsInt <= 122 && charAsInt >= 97) { //122 is the ASCII value of 'z', and 97 is 'a'
                value += (charAsInt - 96); //only subtract 96 because we want 'a' to be 1, not 0
            }
     }
    return value;
}

如果你现在不清楚它的工作原因,那么在检查ASCII到十进制表时会很明显。我们来看看吧。

ASCII to decimal table

记下小写'a'和小写'z'的值。它们分别是我们的下限和上限。我们只是循环遍历每个小写字符,将其转换为带有int强制转换的ASCII十进制值。然后我们用'a'的值减去我们的ASCII值减一。