DAY4 链表part02

 

今日任务

●  24. 两两交换链表中的节点

●  19.删除链表的倒数第N个节点

●  面试题 02.07. 链表相交

●  142.环形链表II

●  总结   //有一定难度,需要好好琢磨

24. 两两交换链表中的节点

用虚拟头结点,这样会方便很多。

题目链接/文章讲解/视频讲解: https://programmercarl.com/0024.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9.html

*注意画图理清思路

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode() : val(0), next(nullptr) {}
 7  *     ListNode(int x) : val(x), next(nullptr) {}
 8  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 9  * };
10  */
11 class Solution {
12 public:
13     ListNode* swapPairs(ListNode* head) {
14         ListNode* dummy=new ListNode(0);
15         dummy->next=head;
16         ListNode* p=dummy;
17         ListNode* q=dummy->next;
18 
19         while(q!=NULL&&q->next!=NULL)
20         {
21             ListNode* tmp=q->next;
22             q->next=tmp->next;
23             tmp->next=q;
24             p->next=tmp;
25 
26             p=p->next->next;//p走两格
27             q=q->next;
28         }
29         head=dummy->next;
30         return head;
31     }
32 };

 

19.删除链表的倒数第N个节点

双指针的操作,要注意,删除第N个节点,那么我们当前遍历的指针一定要指向 第N个节点的前一个节点

题目链接/文章讲解/视频讲解:https://programmercarl.com/0019.%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%ACN%E4%B8%AA%E8%8A%82%E7%82%B9.html

*双指针的经典用法:让fast先走N,再让fast和slow同时走,直到fast到尾结点,此时slow指向目标节点的前一位置,即倒数N+1结点;

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode() : val(0), next(nullptr) {}
 7  *     ListNode(int x) : val(x), next(nullptr) {}
 8  *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 9  * };
10  */
11 class Solution {
12 public:
13     ListNode* removeNthFromEnd(ListNode* head, int n) {
14         ListNode* dummy=new ListNode(0);
15         dummy->next=head;
16         ListNode* fast=dummy;
17         ListNode* slow=dummy;
18         for(int i=0;i<n;i++) fast=fast->next;
19 
20         while(fast->next!=NULL)//注意此条件
21         {
22             fast=fast->next;
23             slow=slow->next;
24         }//出循环时fast指向最后一个节点,slow指向目标节点前一个结点
25         ListNode* tmp=slow->next;
26         slow->next=tmp->next;
27         delete(tmp);
28         //以上三行可写作 slow->next=slow->next->next;
29 
30         head=dummy->next;
31         return head;
32     }
33 };
 

面试题 02.07. 链表相交

题目链接/文章讲解:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html

方法一:让A和B“对齐”,从而同步移动指针,可以找到公共首节点;

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9  //对齐
10 class Solution {
11 public:
12     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
13         int lenA=0;
14         int lenB=0;
15         ListNode* cura=headA;
16         ListNode* curb=headB;
17         while(cura!=NULL) 
18         {
19             lenA++;
20             cura=cura->next;
21         }
22         while(curb!=NULL) 
23         {
24             lenB++;
25             curb=curb->next;
26         }
27         cura=headA;
28         curb=headB;
29         if(lenA>lenB)
30         {
31             int cnt=lenA-lenB;
32             while(cnt--) cura=cura->next;
33         }
34         else if(lenA<lenB)
35         {
36             int cnt=lenB-lenA;
37             while(cnt--) curb=curb->next;
38         }//分类讨论
39         while(cura!=NULL&curb!=NULL)
40         {
41             if(cura==curb) return cura;
42             else 
43             {
44                 cura=cura->next;
45                 curb=curb->next;
46             }
47         }
48         return cura;
49         }
50 };

方法二:合并链表实现同步移动(画图)

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9  //合并链表实现同步移动
10 class Solution {
11 public:
12     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
13         ListNode* curA=headA;
14         ListNode* curB=headB;
15         while(curA!=curB)
16         {
17             if( curA==NULL) curA=headB;
18             else curA=curA->next;
19 
20             if(curB==NULL) curB=headA;
21             else curB=curB->next;
22         }
23         return curA;
24     }//理解
25 };

 

142.环形链表II

题目链接/文章讲解/视频讲解:https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html

*明确任务:判断有无环和找到入环的第一结点

*思想:双指针判断有无环(fast=fast->next->next,slow=slow->next),经证明,若fast和slow相遇,则一定有环且在环内相遇;

   数学证明,若meet从相遇结点出发,index从head出发,则二者会在环的首节点相遇(相同速度);

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     ListNode *detectCycle(ListNode *head) {
12         ListNode *fast=head;
13         ListNode *slow=head;
14 
15         while(fast!=NULL&&fast->next!=NULL)//判断有没有环
16         {
17             slow=slow->next;
18             fast=fast->next->next;
19             if(fast==slow)//有环
20             {
21                 ListNode* meet=slow;//相遇节点
22                 ListNode* index=head;//首节点
23 
24                 while(meet!=index)
25                 {
26                     meet=meet->next;
27                     index=index->next;
28                 }相遇则找到环的入口
29                 return meet;
30             }
31         }
32         
33             return NULL;//没找到
34     }
35 };

 

总结

https://www.programmercarl.com/%E9%93%BE%E8%A1%A8%E6%80%BB%E7%BB%93%E7%AF%87.html

重点:虚拟结点的使用非常重要~

 

posted @ 2024-07-20 22:41  xzdmzrc  阅读(3)  评论(0编辑  收藏  举报