思路講解與演算法實現 LeetCode - 實現 strStr()
阿新 • • 發佈:2021-01-24
聆聽 沉澱 傳播 … 關注微信公眾號【Java之言】,助你放棄程式設計之路!
每天一道演算法題,講解自己解題思路與實現;歡迎大家點評或者說出你的解題想法;也可評論想讓我講解哪道題!
文章目錄
題目
實現 strStr() 函式。
給定一個 haystack 字串和一個 needle 字串,在 haystack 字串中找出 needle 字串出現的第一個位置 (從0開始)。如果不存在,則返回 -1。當 needle 是 空字串 時我們應當返回 0 。
示例1:
輸入: haystack = “hello”, needle = “ll”
輸出:2
示例2:
輸入:haystack = “aaaaa”, needle = “bba”
輸出:-1
示例3:
輸入:haystack = “aaaaa”, needle = “”
輸出:0
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/implement-strstr/
一、思路
字串匹配,
最簡單的
,無非暴力匹配
,但這效率是最低
的。
如果不自己實現,現有很多api都實現了此功能,例如String
的indexOf
方法就能達到此效果。
但是此題目是讓我們自己實現,說到字串匹配問題,最有名的無非是KMP演算法
。
KMP演算法
的核心思想
是用模式串(即本題目的needle)
構建一個next陣列
:
- next陣列各值的含義:代表當前字元之前的字串中,有
多大長度的相同字首
。- 例如如果next[j]=k,代表j之前的字串中有最大長度為k的相同字首。
- 意味著在某個字元失配時,該字元對應的next值會告訴你下一步匹配中,模式串應該跳到哪個位置(跳到next[j]的位置)。
- 如果next[j]等於0,則跳到模式串的開頭字元,若next[j]=k且k>0,代表下次匹配跳到j之前的某個字元,而不是跳到開頭,即跳過了k個字元。
二、演算法實現
package com.nobody;
/**
* @Description 實現 strStr() 函式。 給定一個 haystack 字串和一個 needle 字串,在 haystack 字串中找出 needle
* 字串出現的第一個位置(從0開始)。如果不存在,則返回 -1。
*
* @Author Mr.nobody
* @Date 2021/1/23
* @Version 1.0
*/
public class StrStr {
public static int strStr(String haystack, String needle) {
// 文字串長度小於模式串,明顯匹配不到
if (haystack.length() < needle.length()) {
return -1;
}
// 利用KMP演算法構建next陣列
int[] next = buildNext(needle);
int i = 0, j = 0;
while (i < haystack.length() && j < needle.length()) {
if (haystack.charAt(i) == needle.charAt(j)) {
// 匹配,兩個下標都向後
j++;
i++;
} else if (j == 0) {
// 開頭處匹配失效
i++;
} else {
// 利用KMP,回溯到具體位置
j = next[j];
}
}
return j == needle.length() ? i - j : -1;
}
// KMP演算法
// next陣列各值的含義:代表當前字元之前的字串中,有多大長度的相同字首字尾。
// 例如如果next[j]=k,代表j之前的字串中有最大長度為k的相同字首字尾。
// 意味著在某個字元失配時,該字元對應的next值會告訴你下一步匹配中,模式串應該跳到哪個位置(跳到next[j]的位置)。
// 如果next[j]等於0,則跳到模式串的開頭字元,若next[j]=k且k>0,代表下次匹配跳到j之前的某個字元,而不是跳到開頭,即跳過了k個字元。
private static int[] buildNext(String needle) {
// 記錄模式串needle每個字元匹配失效後應該回溯的位置,即nextArr[j]為在j處匹配失效後,下一個匹配(回溯)的位置,
int[] next = new int[needle.length()];
int j;
// 因為第0個字元匹配失效,肯定還是從0個字元開始,所以i的從1開始
for (int i = 1; i < needle.length(); i++) {
j = i - 1;
while (j > 0 && needle.charAt(i - 1) != needle.charAt(next[j])) {
j = next[j];
}
if (j <= 0) {
next[i] = 0;
} else {
next[i] = next[j] + 1;
}
}
return next;
}
public static void main(String[] args) {
System.out.println(strStr("hello", "ll"));
System.out.println(strStr("aaaaa", "bba"));
System.out.println(strStr("aaaaa", ""));
}
}
輸出結果:
2
-1
0
Leetcode執行結果:
三、上下篇
上一篇:思路講解與演算法實現 LeetCode - 陣列形式的整數加法
下一篇:敬請期待