开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
题目来源:leetcode-cn.com/leetbook/re…
题目
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
输入:haystack = "hello", needle = "ll"
输出:2
思路分析
在 JS 中是有IndexOf方法可以对 字符串可以直接索引定位到子串的位置,那么基本就只要使用一行代码就能实现这个算法。但是如果没有这个方法的话,一个简单的思路就是一个个字符进行匹配:子串从头开始和主串进行匹配,如果匹配失败了,子串再次从头开始匹配,主字符串就下一个字符继续匹配。直到子串都遍历结束都没有中断主串的遍历,那么说明存在,就可以当前的位置减去子串的位置,就是子串的位置。
其实这是一道典型的KMP算法题,KMP算法的本质就是减少重复计算,在上面的解法中我们比较时如果匹配失败那么子串就需要重新计算,想想如果遇到在最后一步比较失败的时候,然后子串又要从头开始,是不是有点像在做无用功,所以KMP算法就是想让你每次检验时,主串要从上一次比较的下一个字符开始,就是我们已经成功后的数据时可以再次利用的
代码实现
public int strStr(String haystack, String needle) {
if (needle.length() == 0)
return 0;
int i = 0;
int j = 0;
int[] next = new int[needle.length()];
getNext(needle, next);
while (i < haystack.length() && j < needle.length()) {
if (j == -1 || haystack.charAt(i) == needle.charAt(j)) {
i++;
j++;
} else {
j = next[j]; // j回到指定位置
}
if (j == needle.length())
return i - j;
}
return -1;
}
private void getNext(String p, int next[]) {
int len = p.length();
int i = 0;
int j = -1;
next[0] = -1;//这个默认的,
while (i < len - 1) {
if (j == -1 || p.charAt(i) == p.charAt(j)) {
i++;
j++;
next[i] = j;
} else
j = next[j];
}
}