Implement strStr()
最新更新:https://yanjia.me/zh/2019/02/…
Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
暴力法
复杂度
时间 O(N^2) 空间 O(1)
思路
本题有很多高级算法可以在O(N)时间内解决问题,然而这已经超出面试的范畴。本题在面试中出现的作用就是考察基本的编程素养,以及边界条件的考虑。我们用暴力法即可。
代码
public class Solution {
public int strStr(String haystack, String needle) {
int start = 0;
// 如果剩下的字母不够needle长度就停止遍历
while(start <= haystack.length() - needle.length()){
int i1 = start, i2 = 0;
while(i2 < needle.length() && haystack.charAt(i1)==needle.charAt(i2)){
i1++;
i2++;
}
if(i2 == needle.length()) return start;
start++;
}
return -1;
}
}
KMP算法
复杂度
时间 O(N+M) 空间 O(M)
思路
KMP算法是较为高级的算法。它使用一个next数组,这个数组记录了模式串needle自身的前缀和后缀的重复情况。同样是双指针进行匹配,当失配时可以根据这个数组找到应该将模式串向后位移多少位,避免一些重复的比较。具体的解法这里有两篇文章比较好,一篇是详细讲解KMP算法。
如果看完对产生next数组的方法还不太明白,还有一篇是讲解next数组怎么得到的。
代码
public class Solution {
public int strStr(String haystack, String needle) {
if(needle.length() == 0){
return 0;
}
int[] next = new int[needle.length()];
// 得到next数组
getNextArr(next, needle);
// i是匹配串haystack的指针,j是模式串needle的指针
int i = 0, j = 0;
// 双指针开始匹配
while(i < haystack.length() && j < needle.length()){
// 如果j=-1意味着刚刚失配过,下标+1后,下一轮就可以开始匹配各自的第一个了
// 如果指向的字母相同,则下一轮匹配各自的下一个
if(j == -1 || haystack.charAt(i) == needle.charAt(j)){
i++;
j++;
// 如果失配,则将更新j为next[j]
} else {
j = next[j];
}
}
return j == needle.length() ? i - j : -1;
}
private void getNextArr(int[] next, String needle){
// k是前缀中相同部分的末尾,同时也是相同部分的长度,因为长度等于k-0。
// j是后缀的末尾,即后缀相同部分的末尾
int k = -1, j = 0;
next[0] = -1;
while(j < needle.length() - 1){
// 如果k=-1,说明刚刚失配了,则重新开始计算前缀和后缀相同的长度
// 如果两个字符相等,则在上次前缀和后缀相同的长度加1就行了
if (k == -1 || needle.charAt(j) == needle.charAt(k)){
k++;
j++;
next[j] = k;
} else {
// 否则,前缀长度缩短为next[k]
k = next[k];
}
}
}
}