昨天论文返修回来啦,马上可以发表啦,可是感觉格式才是最难改的,改了一天还有一些没改完。
目录
一、算法刷题复习
1、KMP算法:
1)实现strStr()
2)重复的子字符串
上述两题的关键思路:求解next数组
1】初始化:左指针j=-1,右指针i=1,next[0]=-1;
2】处理s[j+1] != s[i]的情况(还需要满足j>=0):j持续回退(j=next[j]);
3】处理s[j+1] == s[i]的情况:j++;
4】next数组赋值:next[i] = j;
2、双指针合集
1)翻转字符串里的单词
关键思路:
1】去除多余空格(易错点)
使用扩展双指针法,当fast指向的不为空格,则一直更新s[slow++]=s[fast++](while循环 中),直到遇到空格则停止字符赋值,并手动在单词间添加空格;最后需要重新赋值长度
2】反转整个字符串
3】反转单词
2)翻转链表
关键思路:
定义指针pre与cur,并且在while循环中需要temp记录cur->next节点,更新指针指向位置
3)两两交换链表中的节点
需要创建虚拟头节点
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
ListNode* cur = dummyHead;
while(cur->next != nullptr && cur->next->next != nullptr) {
ListNode* tmp = cur->next; // 记录临时节点
ListNode* tmp1 = cur->next->next->next; // 记录临时节点
cur->next = cur->next->next; // 步骤一
cur->next->next = tmp; // 步骤二
cur->next->next->next = tmp1; // 步骤三
cur = cur->next->next; // cur移动两位,准备下一轮交换
}
return dummyHead->next;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
4)删除链表的倒数第N个节点
注意:需要添加虚拟头节点(总结链表需要添加虚拟头节点的情况)
关键思路:先让fast指针走N步,然后再让slow与fast同时向后走,直到fast指向末尾,此时slow指向需要删除节点的前一个节点,最后进行删除操作slow->next=slow->next->next。
5)链表相交
注意:由于指针同一时刻只能指向一个地址因此两链表相交只可能在最后几个位置的节点。
关键思路:将两链表末尾对其,将长度较长的链表指针移动到与短链表开头的位置一致的位置,然后逐个将长链表的后面几个节点与短链表节点逐一对比,如果完全一致则说明相交
具体步骤:
简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
6)环形链表
关键思路:理论推导参考:代码随想录 (programmercarl.com)
7)三数之和,四数之和
三数之和关键思路:(易错点与难点:去重),参考:代码随想录 (programmercarl.com)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size(); i++){
if(nums[i] > 0){
return res;
}
if(i>0 && nums[i] == nums[i-1]){
continue;
}
// for(int j=i; j<s.size(); j++){
// int k = s.size()-1;
// if(nums[i]+nums[j]+nums[k] < 0){
// j++;
// }else if(nums[i]+nums[j]+nums[k] > 0){
// k--;
// }else{
// while(nums[j] == nums[j+1] && j<s.size()) j++;
// while(nums[k] == nums[k-1] && k>j) k--;
// res.insert(i,j,k);
// }
// }
int j = i+1;
int k = nums.size()-1;
while(j < k){
if(nums[i]+nums[j]+nums[k] < 0){
j++;
}else if(nums[i]+nums[j]+nums[k] > 0){
k--;
}else{
res.push_back(vector<int>{nums[i], nums[j], nums[k]});
// 错误写法:注意要先判断j<k否则报错,因为需要想先判断是否满足j<k
// while(nums[j] == nums[j+1] && j<k) j++;
// while(nums[k] == nums[k-1] && j<k) k--;
while(j<k && nums[j] == nums[j+1]) j++;
while(j<k && nums[k] == nums[k-1]) k--;
j++;
k--;
}
}
}
return res;
}
};
四数之和与上述基本一致