28. 实现 strStr()
链接:https://leetcode-cn.com/problems/implement-strstr/
实现strStr()
函数。
给你两个字符串haystack
和needle
,请你在haystack
字符串中找出needle
字符串出现的第一个位置(下标从0
开始)。如果不存在,则返回-1
。
输入:haystack = "hello", needle = "ll"
输出:2
输入:haystack = "aaaaa", needle = "bba"
输出:-1
输入:haystack = "", needle = ""
输出:0
解法1:暴力匹配(朴素匹配)
最初的想法,是对haystack
和needle
进行逐个匹配,其实只需要按照needle
的长度进行循环即可(就连这个一开始都没有想到,太菜了)
var strStr = function (haystack, needle) {
if (!needle) {
return 0;
}
const length1 = haystack.length,
length2 = needle.length;
const length = length1 - length2;
let found = false;
for (let i = 0; i <= length; i++) {
found = true;
for (let j = 0; j < length2; j++) {
if (haystack[i + j] !== needle[j]) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1;
};
- 时间复杂度:
n
为原串的长度,m
为匹配串的长度,整体复杂度为${O(n-m) * m}$
- 空间复杂度:
${O(1)}$
- 执行结果:执行用时96ms,在所有JavaScript提交中击败了36.58%的用户,内存消耗:38.6MB,在所有JavaScript提交中击败了53.26%的用户
解法2:KMP解法
(有一点复杂,脑子又有点不转了)
关于KPM解法的原理,看『宫水三叶』简单题学KMP算法这篇解答吧
抄一下官方的答案吧,以后看到这段代码肯定是又想不起来怎么回事了,结合上面的解答重新理解一下吧笨蛋
var strStr = function (haystack, needle) {
if (!needle) {
return 0;
}
const n = haystack.length,
m = needle.length;
const next = new Array(m).fill(0);
// 预处理 next 数组, 数组长度为匹配穿的长度
for (let i = 1, j = 0; i < m; i++) {
// 匹配不成功的话, j 向后退
while (j > 0 && needle[i] !== needle[j]) {
j = next[j - 1];
}
// 匹配成功的话,j 向前走
if (needle[i] === needle[j]) {
j++;
}
// 更新 next[i]
next[i] = j;
}
// 真正的匹配过程开始
for (let i = 0, j = 0; i < n; i++) {
// 匹配不成功,匹配串移动到 next 数组存储的位置
while (j > 0 && haystack[i] !== needle[j]) {
j = next[j - 1];
}
// 匹配成功,j 向前走
if (haystack[i] === needle[j]) {
j++;
}
// 整一段匹配成功,直接返回下标
if (j === m) {
return i - m + 1;
}
}
return -1;
};