看见题目,一眼用indexOf,但是这样子貌似就没有做题的必要了
indexOf
var strStr = function(haystack, needle) {
return haystack.indexOf(needle)
};
暴力破解
var strStr = function (haystack, needle) {
let n = haystack.length
let m = needle.length
for (let i = 0; i <= n - m; ++i) {
if (needle === haystack.slice(i, i + m)) {
return i
}
}
return -1
};
var strStr = function (haystack, needle) {
let i = 0,
j = 0;
while (i < haystack.length && j < needle.length) {
if (haystack[i] !== needle[j]) {
i = i - j + 1;
j = 0;
} else {
i++;
j++;
}
if (j === needle.length) {
return i - needle.length;
}
}
return -1;
};
KMP算法
错误代码
var strStr = function (haystack, needle) {
let i = 0,
j = 0;
while (i < haystack.length && j < needle.length) {
if (haystack[i] !== needle[j]) {
j = 0;
i++;
} else {
i++;
j++;
}
if (j === needle.length) {
return i - needle.length;
}
}
return -1;
};
对于上面的代码,可以看到,其实可以通过很多测试用例,主要的错误在于i的位置如何重置的这个问题
i如果要暴力穷举的话,那么就要在上次的开始的地方的下一位,也就是 i = i - j + 1,这个位置上
但是此时i的位置是直接i++,没有把前面区间穷举
在下面这个测试用例里面可以看到,此时i,j指向的地方不想等,那么就要挪动i,恢复j = 0
i
mississippi
issip
j
所以,从上面这段错误的代码,以及通过的测试用例里面可以看到,主要看
i如何到下一个位置。
对于暴力穷举来说,肯定不会漏掉,但是要节约时间,那么就要看i如何抉择了
正确代码
var strStr = function (haystack, needle) {
let n = haystack.length
let m = needle.length
let lps = new Array(m).fill(0)
let j = 0
// 计算next数组
for (let i = 1; i < m; ++i) {
while (j > 0 && needle[i] !== needle[j]) j = lps[j - 1]
if (needle[i] === needle[j]) j++
lps[i] = j
}
j = 0
for (let i = 0; i < n; ++i) {
// 回溯
while (j > 0 && needle[j] !== haystack[i]) j = lps[j - 1]
if (needle[j] === haystack[i]) j++
// 返回起始位置
if (j === m) return i - m + 1
}
return -1
};