基础算法精讲 08|前后指针|链表
前后指针针对链表
看见删除结点,我们就知道需要有当前结点cur,和前驱结点pre。所以立马用前后指针的思想。
237. 删除链表中的节点
237. 删除链表中的节点
思路
这道题细思极恐:如何让自己在世界上消失,但又不死? —— 将自己完全变成另一个人,再杀了那个人就行了。
简称杀我不死
删除结点不能是最后一个
完整代码
class Solution {
public:void deleteNode(ListNode* node) {node->val = node->next -> val;node->next = node->next->next;}
};
遇到的问题
c++中需要自动释放内存。但力扣里不需要。
19. 删除链表的倒数第 N 个结点
19. 删除链表的倒数第 N 个结点
思路
- 使用了前后指针。
- 设置两个指针pre和cur,让cur开始时比pre快n步,那么只要cur遍历到末尾时,pre指向的就是倒数第n个。但是删除一个结点要知道删除节点的前一个结点,所以我们一开始就让cur比pre快n+1步,这样pre指向倒数n+1个,那就好删除倒数第n个了。
- 删除头结点的时候没有前驱结点,使用要设置dummy结点,使得头结点与后面的结点统一。
完整代码
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode dummy(0, head);ListNode *cur = &dummy;ListNode *pre = &dummy;while(n+1>0){cur = cur->next;n--;}while(cur){cur = cur->next;pre = pre->next;}pre->next = pre->next->next;return dummy.next;}
};
83. 删除排序链表中的重复元素
83. 删除排序链表中的重复元素
思路
- 前后指针。当前后指针
完整代码
class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {//防一手空链表。空链表时ListNode *cur = head->next会报错。if (head == nullptr) return nullptr;ListNode *pre = head;ListNode *cur = head->next;while(cur){if (pre->val==cur->val){pre->next = pre->next->next;cur = cur->next;}else{pre = pre->next;cur = cur->next;}}return head;}
};
82. 删除排序链表中的重复元素 II
82. 删除排序链表中的重复元素 II
思路
- 前后指针删除排序链表中的重复元素。比如1222333==》123
- 再设置一个pre指针用来删除结点。
- 我犯了一个错误,还在用237.删除链表中的节点中的杀我不死的方法。其实一个前置指针就搞定。杀我不死有局限性不能是最后一个结点被删除,所以不能用这个方法。
完整代码
class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {ListNode *dummy = new ListNode(666, head);ListNode *pre = dummy;ListNode *cur = head;if(cur==nullptr||cur->next==nullptr)return cur;while(cur && cur->next){if(cur->val == cur->next->val){while(cur->next && cur->val==cur->next->val)cur->next = cur->next->next;pre->next = pre->next->next;cur = cur->next;}else{pre = pre->next;cur = cur->next;}}return dummy->next;}
};203.移除链表元素
203. 移除链表元素
 
思路
移除肯定是前后指针啊
完整代码
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode *dummy = new ListNode(0, head);ListNode *pre = dummy;ListNode *cur = head;while(cur){if(cur->val==val){pre->next = pre->next->next;cur = pre->next;}else{cur = cur->next;pre = pre->next;}}return dummy->next;}
};
3217. 从链表中移除在数组中存在的节点
3217. 从链表中移除在数组中存在的节点
思路
- 一个链表一个数组。将数组变成哈希表
- 将数组中的元素放入哈希表里面。这样遍历链表元素, 同时if(st.find(p->next->val)!=st.end())。一旦if为true,就移除该节点。
- 为什么要用哈希表?因为哈希表的查找是O(1).如果用原来的数组查找是O(n)。
完整代码
class Solution {
public:ListNode* modifiedList(vector<int>& nums, ListNode* head) {/*unordered_map<int,int> st;for(auto c:nums)st[c]++;*/unordered_set<int> st(nums.begin(), nums.end());ListNode *t=new ListNode;t->next=head;ListNode *p=t;while(p->next){/*map的判断条件   st.find(p->next->val)!=st.end()*/if(st.contains(p->next->val))p->next=p->next->next;elsep=p->next;}return t->next;}
};
遇到的问题
unordered_map<int,int> st;for(auto c:nums)st[c]++;
unordered_map是一个无序的容器,key值不能重复,value可以重复。
2487.从链表中移除结点
理解不了,算了算了
1669.合并两个链表
1669. 合并两个链表
思路
太简单了吧
完整代码
class Solution {
public:ListNode* mergeInBetween(ListNode* list1, int a, int b, ListNode* list2) {ListNode *aPre = list1;//找到a前面一个结点for (int i = 0; i < a-1 ;i++){aPre = aPre->next;}//找到list2最后一个结点ListNode *l2_tail = list2;while(l2_tail->next){l2_tail = l2_tail->next;}//找到b后面一个结点ListNode *bNxt = list1;for (int j = 0; j < b + 1;j++){bNxt = bNxt->next;}//合并链表aPre->next = list2;l2_tail->next = bNxt;return list1;}};
