给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
示例 1:
输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
示例 2:
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。
提示:
- 1 <= haystack.length, needle.length <= 104
- haystack 和 needle 仅由小写英文字符组成
解答
遍历 haystack,当 haystack[i] === needle[0]时,再比较 haystack[i + 1] 与 needle[1]是否相等,haystack[i + 2] 与 needle[2] 是否相等,一直到 haystack[i + needle.length - 1] 与 needle[needle.length - 1] 是否相等。这个过程一共有两层遍历,当 haystack[i] === needle[0] 满足时,才开始第二层遍历
ini
function strStr(haystack: string, needle: string): number {
let index = -1
let i = 0
while(i < haystack.length) {
if (haystack[i] === needle[0]) {
let step = 1
let isInclude = true
while(step < needle.length) {
if (haystack[i + step] !== needle[step]) {
isInclude = false
break
}
step++
}
if (isInclude) {
index = i
break
}
}
i++
}
return index
};
空间复杂度O(1),时间负责度O(m * n)

needle 是 haystack 的一部分,意味着 haystack 的长度不小于 needle 的长度,因此对上面的解答进行优化
ini
function strStr(haystack: string, needle: string): number {
let index = -1
let i = 0
while(i < haystack.length) {
if (haystack.length - i < needle.length) {
break
}
if (haystack[i] === needle[0]) {
let step = 1
let isInclude = true
while(step < needle.length) {
if (haystack[i + step] !== needle[step]) {
isInclude = false
break
}
step++
}
if (isInclude) {
index = i
break
}
}
i++
}
return index
};

在上述解法中,每一次遇到不匹配的位置都是将 needle 往后移动一步,利用KMP算法计算出部分匹配表,动态计算需要移动的步数
ini
function strStr(haystack: string, needle: string): number {
const n = haystack.length, m = needle.length;
let index = -1
let i = 0
// 部分匹配表
const pi = new Array(m).fill(0);
for (let i = 1, j = 0; i < m; i++) {
while (j > 0 && needle[i] !== needle[j]) {
j = pi[j - 1];
}
if (needle[i] == needle[j]) {
j++;
}
pi[i] = j;
}
while(i < n) {
let j = 1
if (n - i < m) {
break
}
if (haystack[i] === needle[0]) {
let step = 1
let isInclude = true
while(step < m) {
if (haystack[i + step] !== needle[step]) {
isInclude = false
// needle 移动步数 = 已匹配的字符数 - 对应的部分匹配值
j = step - pi[step-1]
break
}
step++
}
if (isInclude) {
index = i
break
}
}
i += j
}
return index
};
时间复杂度O(m+n),空间复杂度O(m)