链表中前后指针法总结
链表中前后指针法总结
本文将持续更新
模型一:交换链表元素
206. 反转链表
1.思路
链表中的前后指针法,通常是为了记录当前元素的前一个元素的,因为单链表是没法去寻找前面的元素的。这样也可以在只遍历一次链表的情况下解决问题。
思路很简单,只要理清楚各个链表元素的链接顺序即可,即如何交换才能让我们拿到所有需要的元素。
2.实现
class Solution { public: ListNode* reverseList(ListNode* head) { ListNode* cur=head; ListNode* prev=nullptr; while(cur) { ListNode* next=cur->next; cur->next=prev; prev=cur; cur=next; } return prev; } };
24. 两两交换链表中的节点
class Solution { public: ListNode* swapPairs(ListNode* head) { ListNode* dummyhead=new ListNode(); dummyhead->next=head; ListNode* cur=dummyhead; while(cur->next!=nullptr&&cur->next->next!=nullptr) { ListNode* next=cur->next; ListNode* nnext=next->next; ListNode* nnnext=nnext->next; cur->next=nnext; nnext->next=next; next->next=nnnext; cur=next; } return dummyhead->next; } };
模型二:找规定位置
19. 删除链表的倒数第 N 个结点
1.思路
这一类题的前后指针,往往先让快指针向前前进,然后快慢指针一起前进,最终慢指针的位置就是我们需要的位置。
关键在于在题干中分析出来快指针到底走多远,慢指针才开始走。
2.实现
class Solution { public: ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* dummyhead=new ListNode(); dummyhead->next=head; ListNode* fast=dummyhead; ListNode* slow=dummyhead; int count=0; while(count<=n) { fast=fast->next; count++; } while(fast!=nullptr) { fast=fast->next; slow=slow->next; } ListNode* next=slow->next; slow->next=next->next; delete next; return dummyhead->next; } };
模型三:环形链表
142. 环形链表 II
1.思路
只需要记住三点,找到两个位置,题就可以解了。
- 快指针每次比慢指针多走1步
- 快指针会和慢指针在环中的某一个位置相遇
- 从相遇位置和起始位置以相同的速度同时出发,最终会在环的入口处相遇
2.实现
public: ListNode *detectCycle(ListNode *head) { ListNode* fast=head; ListNode* slow=head; while(fast&&fast->next&&slow) { fast=fast->next->next; slow=slow->next; if(fast==slow) { break; } } if(fast==nullptr||fast->next==nullptr) { return nullptr; } ListNode* res=head; while(res!=slow) { res=res->next; slow=slow->next; } return res; } };
总结
链表中的前后指针法和数组中的前后指针法处理的问题是不同的,注意区分。
#算法#