演算法13 leetcode28 實現 strStr()
阿新 • • 發佈:2021-11-06
目錄
用indexOf()就沒意思了
用indexOf()就沒意思了
題目
實現strStr()函式。
給你兩個字串haystack 和 needle ,請你在 haystack 字串中找出 needle 字串出現的第一個位置(下標從 0 開始)。如果不存在,則返回 -1 。
說明:
當needle是空字串時,我們應當返回什麼值呢?這是一個在面試中很好的問題。
對於本題而言,當needle是空字串時我們應當返回 0 。這與 C 語言的strstr()以及 Java 的indexOf()定義相符。
示例 1:
輸入:haystack = "hello", needle = "ll"
輸出:2
示例 2:
輸入:haystack = "aaaaa", needle = "bba"
輸出:-1
示例 3:
輸入:haystack = "", needle = ""
輸出:0
提示:
0 <= haystack.length, needle.length <= 5 * 104
haystack 和 needle 僅由小寫英文字元組成
作者:力扣 (LeetCode)
連結:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnr003/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
我的雙指標
和滾動視窗大同小異
class Solution { public int strStr(String haystack, String needle) { if(needle=="") return 0; char[] h=haystack.toCharArray(); char[] n=needle.toCharArray(); for(int i=0;i<h.length;i++){ if(h[i]==n[0]){ int d=0; int a=i; for(;((d<n.length)&&a<h.length);a++,d++){ if(h[a]!=n[d]) break; else if (d==n.length-1) return a-d; } } } return -1; } }
滾動視窗(參考)
class Solution {
public int strStr(String haystack, String needle) {
int windowSize = needle.length();
if (windowSize == 0) {
return 0;
}
int j = 0;
for (int i = 0; i < haystack.length(); i++) {
if (haystack.charAt(i) == needle.charAt(j)) {
if (j == windowSize - 1) {
return i - windowSize + 1;
}
j++;
} else {
i -= j;
j = 0;
}
}
return -1;
}
}
參考KMP
public int strStr(String haystack, String needle) {
if (needle.length() == 0)
return 0;
int i = 0;
int j = 0;
/**
* 陣列next表示pattern指定的下標前具有相同的字串數量,語言組織能力不好,可能不是太好理解,我舉個例子吧
* ,比如ABCABA,陣列next[0]是-1,這個是固定的,因為第一個A前面是沒有字元的,next[1]是0,因為B的前面就一個A,沒有
* 重複的,所以是0,同理next[2]也是,next[3]也是0,而next[4]是1,因為next[4]所指向的是第二個B,第二個B前面有一個A和
* 第一個A相同,所以是1,next[5]是2,因為next[5]所指向的是最後一個A,因為前面的A對比成功,並且B也對比成功,所以是2,
* 也就是AB兩個字串匹配成功,再舉個例子,比如WABCABA,陣列除了第一個為-1,其他的都是為0,因為只有第一個匹配成功之後
* 才能匹配後面的,雖然後面的AB和前面的AB匹配成功,但是後面AB的前面是C和前面AB的前面一個W不匹配,所以後面的匹配都是0.
* 要記住只有指定字元前面的字元和第一個字元匹配成功的時候才能往後匹配,否則後面的永遠都是先和第一個匹配。
*/
int[] next = new int[needle.length()];
getNext(needle, next);
while (i < haystack.length() && j < needle.length()) {
/**
* 這裡j等於-1的時候也只有在下面next陣列賦值的時候才會出現,並且只有在陣列next[0]的時候才會等於-1,
其他時候是沒有的,這一點要謹記,待會下面求next陣列的時候就會用到。這裡可以這樣來理解,如果j不等於-1,
並且下標i和j所指向的字元相等,那麼i和j分別往後移一位繼續比較,這個很好理解,那麼如果j==-1的時候,就表示
就表示前面沒有匹配成功的,同時i往後移一位,j置為0(j==-1的時候,j++為0),再從0開始比較。
*/
if (j == -1 || haystack.charAt(i) == needle.charAt(j)) {
i++;
j++;
} else {
/**
* i = i - j + 1;
j = 0;
返回到指定的位置,不是返回到匹配失敗的下一個位置,這裡都好理解,重點是求陣列next。
這裡只要j等於0,在next[j]賦值的之後,j就會等於-1;因為next[0]等於-1
*/
j = next[j]; // j回到指定位置
}
if (j == needle.length())
return i - j;
}
return -1;
}
private void getNext(String p, int next[]) {
int len = p.length();
int i = 0;
int j = -1;
next[0] = -1;//這個預設的,
/**
* 匹配的時候是當前字元的前一個和前面的匹配,所以最後一個是不參與匹配的,可以看strStr方法的註釋,
*/
while (i < len - 1) {
if (j == -1 || p.charAt(i) == p.charAt(j)) {
/**
* 如果j不等於-1,指定的字元相等,那麼i和j要往後移一位,這點很好理解,如果j為-1的時候,i往後移移位,j置為0
* 重新開始匹配。next[i]是匹配成功的數量
*/
i++;
j++;
next[i] = j;
} else
/**
* 關鍵是這裡不好理解,為什麼匹配失敗要讓next[j]等於j,要記住這裡的next[j]是指匹配成功的數量,有可能為0,也有可能是其他數.比如
* 字串ABCABXYABCABATDM,對應的next陣列為{-1 0 0 0 1 2 0 0 1 2 3 4 5 1 0 0 }
*/
j = next[j];
}
}