双指针(双向指针、快慢指针(滑动窗口))
//快慢指针
int slowIndex = 0;
for(int fastIndex = 0; fastIndex < nums.size();i++)
{
if(nums[fastIndex]满足某个条件){
nums[slowIndex++] = nums[fastIndex];
}
}
//双向指针
for(int i = 0, j = nums.size()-1; i < j; i++, j--)
{
}
经典应用1::双指针去除string两端的空格,单词间的空格只保留一个
void trimKG(string&s){
int slow = 0;
for(int f = 0; f < s.length();f++){
if(s[f]!=' '){
if(slow!=0) s[slow++] = ' ';
while(f<s.length()&&s[f]!=' '){
s[slow++] = s[f++];
}
}
}
s.resize(slow);
}
经典应用2:删除链表的倒数第n个节点
//快慢指针法
//先让快指针先走n+1步,当快指针走到链表末尾的时候NULL,慢指针恰好指向被删元素的前一个节点
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* slow = dummyHead;
ListNode* fast = dummyHead;
while(n-- && fast != NULL) {
fast = fast->next;
}
fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyHead->next;
}
经典应用3:判断链表中是否有环、(如果无环还可以找到链表的中点)
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
if(fast==slow) 有环;
}
跳出循环无环;
此时slow指向链表中点;
经典应用4:判断链表中环的起点
回溯模板
//伪代码
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
int main(){
选择初始点,开始递归调用;
}
//实现
vector<vector<int>> result; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件结果
void backtracking(int n, int k, int startIndex) //参数可调整
{
if (path.size() == k) {
result.push_back(path);
return;
}
for (int i = startIndex; i <= n; i++) { // 控制树的横向遍历
path.push_back(i); // 处理节点
backtracking(n, k, i + 1); // 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始
path.pop_back(); // 回溯,撤销处理的节点
}
}
单调栈
BFS模板
queue<类型> que;
if(首个不为空) que.push(首个);
while(!que.empty()){
int size = que.size();
for(int i = 0; i < size; i++){
取出元素xxx = que.front();
弹出 que.pop();
对xxx进行处理;
将周围的元素加入;
}
}