簡體   English   中英

在char []中搜索char與使用String.indexOf()方法搜索String之間有什么區別?

[英]What is the difference between searching for a char in a char[] vs searching for a String using the String.indexOf() method?

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問題42時 ,我得到了不同的結果。 上面顯示的第一個“ for”循環輸出正確的結果,第二個“ for”循環輸出錯誤的結果。

上面的代碼接受一個String並返回其word值。 例如,單詞SKY將返回單詞值55,因為該單詞中的字母按如下方式添加(從1開始):

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

19 + 11 + 25 = 55。

我已將問題簡化為上述代碼,並且不明白為什么會發生這種情況。 也許我錯過了與Java String類及其方法有關的重要信息。

我正在Windows 10的Eclipse Neon.3 Release(4.6.3)中運行Java 8。

這兩段代碼完全不同。

在這兩種情況下,您都有一個外部循環,該循環為可變letter中的字符串alpha每個字符提供服務。

在第一種情況下,您將擁有一個內部循環,該循環遍歷字符串word 每個字符並計算letter 每個匹配出現。 當內循環計算出word 每個 letter出現次數時,外循環將移至下一個letter

在第二種情況下,沒有內部循環。 每次圍繞外循環,您都使用word.indexOf(letter)嘗試查找word 第一個出現letter的索引。 如果有一個,則增加計數。 無論哪種方式,您都已經完成了該letter ,外循環繼續到下一個letter word可能還存在其他letter ,但是這種情況並未嘗試找到它們並對其進行計數。

在第二種實現中,對於多次包含某些字母的單詞,單詞值不正確。 例如,對於WOOD,第一種方法將計算3 + 14 + 14 + 22,但是第二種方法將計算3 + 14 + 22。

為什么? 第一種方法遍歷單詞的字符:

 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; } } 

因此,在“ WOOD”的示例中,“ O”將僅計數一次,而不是兩次。


順便說一句,到String的轉換在這里毫無意義:

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

編寫相同內容的更好方法:

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

(但是實現仍然是不正確的。)


最后,如果字母是英語AZ,則可以實現更快的實現:

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

return totalWordValue;

indexOf有4個重載方法,其中一個重載方法( character參數除外),並返回字符序列中字符首次出現的索引。

現在,問您一個問題。 在您的方案中indexOfcharAt行為相同,因為您僅傳遞了字符。 而且,從內部開始,但是,想象一下,您有一個String並且想要從另一個長String進行檢查並獲取它的索引。 那你會怎么做? indexOf

我知道這並不一定能解決您關於上述方法之間的區別的問題,但是其他人對此已回答得足夠好。

您想要一個字符串字母的字母位置的總和嗎? 我們可以使用某種算法在一個循環中完成此操作,而無需增加內部循環或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到十進制表

記下小寫字母“ a”和小寫字母“ z”的值。 它們分別是我們的下限和上限。 我們只需循環遍歷每個小寫字符,並使用int強制轉換將其轉換為ASCII十進制值。 然后,我們將ASCII值減去“ a”的值再減去一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM