28. 实现 strStr()
题目链接:28. 实现 strStr()
文档讲解:代码随想录
思路
KMP算法是利用前缀表来记录已经匹配过的信息,每次遇到不匹配的情况时,跳回到上次匹配到的地方开始匹配。
第一次写KMP算法,跟着B站视频大体弄明白了算法原理。
代码
class Solution {
public:
int strStr(string haystack, string needle) {
int next[needle.size()];
GetNext(next, needle);
int j = 0;
for (int i = 0; i < haystack.size(); i++) {
while (j > 0 && haystack[i] != needle[j])
j = next[j - 1];
if (haystack[i] == needle[j])
j++;
if (j == needle.size())
return (i - needle.size() + 1);
}
return -1;
}
void GetNext(int *next, string s) {
int j = 0;
next[0] = j;
for (int i = 1; i < s.size(); i++) {
while (j > 0 && s[j] != s[i]) {
j = next[j - 1];
}
if (s[j] == s[i])
j++;
next[i] = j;
}
}
};
459.重复的子字符串
题目链接:459. 重复的子字符串
文档讲解:代码随想录
思路
根据B站视频所讲,由重复子字符串组成的字符串的最大相等前后缀与原字符串相差一个重复的子字符串,而原字符串是由子字符串重复组成,所以子字符串长度一定能整除原字符串长度。
根据上述思路写出的代码在力扣上可以AC。但是我觉得这种B站只讲了这种思路的必要性,但是没有讲解其充分性。
代码
class Solution {
public:
bool repeatedSubstringPattern(string s) {
if (s.size() == 0)
return false;
int next[s.size()];
GetNext(next, s);
int len = s.size();
if (next[len - 1] != 0 && len % (len - next[len - 1]) == 0)
return true;
return false;
}
void GetNext(int *next, string s) {
int j = 0;
next[0] = j;
for (int i = 1; i < s.size(); i++) {
while (j > 0 && s[j] != s[i])
j = next[j - 1];
if (s[j] == s[i])
j++;
next[i] = j;
}
}
};
字符串总结
字符串问题使用最多的方法还是双指针法,不同的只是对双指针的操作,因此双指针法必须熟练掌握。
双指针回顾
27. 移除元素 这道题使用快慢指针,快指针指向需要保留的元素,跳过要删除元素,慢指针指向新数组的下标位置,将快指针所指元素赋值到慢指针所指下标位置,完成移除元素操作。
344. 反转字符串 这道题使用相向双指针,每次交换左右两个指针所指向的元素即可。
54. 替换数字 这道题目先求出新字符串的长度,然后使用两个指针分别指向旧字符串的元素和新字符串的下标位置,将旧字符串的字母元素按顺序赋值给新字符串,旧字符串的数字替换为替换值。
151. 反转字符串中的单词 这道题目使用 27. 移除元素 中双指针的思路移除字符串中多余的空格,然后使用 344. 反转字符串 中双指针的思路分别反转整个字符串和每个单词。
206. 反转链表 这道题目使用双指针分别指向当前反转结点和其前驱结点,每次反转时,使用临时结点记录下反转结点的后继节点,然后改变反转结点的next
指针。
19. 删除链表的倒数第 N 个结点 这道题目使用双指针找出相对尾结点N个的位置,然后使后指针走到链表末尾,前结点即为要删除的结点。
面试题 02.07. 链表相交 这道题先求出两个链表的长度,然后使用指针将两个链表进行尾对齐找出对齐后的起始结点,然后遍历后面的结点,找出相交结点。
142. 环形链表 II 这道题首先使用快慢指针判断链表是否有环,若有环则根据数学推导,在快慢指针相遇处设置指针1,在链表起点处设置指针2,然后一起向后走,相遇点就是环的入口。
15. 三数之和 先将数组进行升序排序,然后进行遍历,如果当前遍历元素与上一次遍历元素相同,则跳过当次遍历避免重复。遍历时设置左右指针,如果当前元素、左指针元素与右指针元素和小于目标值,则左指针右移,若大于目标值,则右指针左移,若等于目标值则将结果添加至结果数组,并通过while
循环将左右指针值完全跳过避免重复。