第28题:实现 strStr()
这题是看第二个字符串是否能匹配上第一个字符串的一部分
我这个前端半吊子第一眼只能想到两个办法
办法一:如果两个循环套用可以解决(这种太暴力了,肯定不行)
办法二:如果是直接用js的API(indexOf)也可以快速解决(这种简单,但是感觉失去了这个题目的意义)
var strStr = function(haystack, needle) {
if (!needle) {
return 0
} else if (!haystack) {
return -1;
} else if (needle.length > haystack.length) {
return -1;
} else {
return haystack.indexOf(needle);
}
}
然后打开评论区发现一个没见过的字眼KMP
这个KMP见都没有见过,然后我就百度了一波,就找到知乎上的这个问题如何更好地理解和掌握 KMP 算法
默认回答排序第一的大佬讲的很详细 但是我只看了一半
果然这里两个循环是最暴力的解决办法(Brute-Force)
我理解KMP就是先给“模式串”,定义一个next数组,数组里面每个值对应“模式串”的每一个字符串,这样在第一层循环的时候,可以跳过一些没必要的过程。
一开始我以为这样可以求出next数组,谁知道,我太年轻了
// 这个是错误的
function next(needle) {
const next = [0];
next.length = needle.length;
for (let i = 1; i < needle.length;i++) {
if (needle[next[i-1]] === needle[i]) {
next[i] = next[i-1] + 1;
} else {
next[i] = 0;
}
}
return next;
}
console.log(next('abcabd')) // [0, 0, 0, 1, 2, 0]
console.log(next('abcabdab')) // [0, 0, 0, 1, 2, 0, 1, 2]
第71个用例直接报错
经过十几分钟的分析,才发现是next数组有问题
console.log(next('aabaaac')) // [0, 1, 0, 1, 2, 0, 0]
这里第一眼看的没有问题,但是人工分析一波,这个数组应该是[0, 1, 0, 1, 2, 2, 0],c前面的那个a,对应的数字应该是2,而不是0,就是这里是0,导致我把正确答案给跳过了。
然后我花了几十分钟分析并修改了一下这里的创建next数组的方法
function next(needle) {
const next = [0];
next.length = needle.length;
function content(i,j) {
if (needle[next[j]] === needle[i]) {
next[i] = next[j] + 1;
} else if (j === 0) {
next[i] = 0;
} else {
content(i,next[j-1]);
}
}
for (let i = 1; i < needle.length;i++) {
content(i,i-1);
}
return next;
}
console.log(next('aabaaac')) // [0, 1, 0, 1, 2, 2, 0]
这次总没有问题了吧
var strStr = function(haystack, needle) {
if (!needle) {
return 0
} else if (!haystack) {
return -1;
} else if (needle.length > haystack.length) {
return -1;
} else {
const next = [0];
next.length = needle.length;
function content(i,j) {
if (needle[next[j]] === needle[i]) {
next[i] = next[j] + 1;
} else if (j === 0) {
next[i] = 0;
} else {
content(i,next[j-1]);
}
}
for (let i = 1; i < needle.length;i++) {
content(i,i-1);
}
let i = 0;
let y = 0;
while (i < haystack.length - needle.length + 1) {
while(y < needle.length) {
if (haystack[i + y] === needle[y]) {
y++;
} else {
break;
}
}
if (y === needle.length) {
return i;
} else if (y === 0){
i++;
} else {
i = (i + y - next[y - 1]);
y = next[y - 1];
}
}
return -1;
}
};
这次问题是没了,还可以运行起来,就是这执行用时太长了