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

声明一个虚拟头节点和当前指针。当前指针初始为虚拟头节点。

遍历链表,交换指针的下一节点和下下节点。如果为节点个数为奇数,最后一个不做操作。

 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* preHead = new ListNode(-1);
15         preHead->next = head;
16         ListNode* curr = preHead;
17         while(curr != nullptr && curr->next != nullptr){
18             ListNode* tmp = curr->next;
19             // 如果节点个数为奇数,最后一个跳出
20             if(tmp->next == nullptr)    break;
21             curr->next = tmp->next;
22             tmp->next = curr->next->next;
23             curr->next->next = tmp;
24             // 交换完成后指针后移两位
25             curr = curr->next->next;
26         }
27         return preHead->next;
28     }
29 };

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

声明虚拟头节点,快慢指针都指向虚拟头节点,先将快指针移动n次

遍历链表,直到快指针指向末尾,此时慢指针下一个就是要删除的节点

 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* dummyNode = new ListNode(0);
15         dummyNode->next = head;
16         ListNode* fast = dummyNode;
17         ListNode* slow = dummyNode;
18         while(n--){
19             fast = fast->next;
20         }
21         while(fast->next!=nullptr){
22             slow = slow->next;
23             fast = fast->next;
24         }
25         // 删除slow->next
26         ListNode* tmp = slow->next;
27         slow->next = slow->next->next;
28         delete tmp;
29         return dummyNode->next;
30     }
31 };

面试题 02.07. 链表相交

分别求出两个链表的长度,然后末尾对齐。

较短的指针指向头节点,较长的指针后移长度差,使两个链表距离末尾长度相同。

最后挨个比较当前节点是否相同,相同则返回。到最后都不同则返回空。

 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 *getIntersectionNode(ListNode *headA, ListNode *headB) {
12         // A,B的长度
13         int m = 0,n = 0;
14         ListNode* currA = headA;
15         ListNode* currB = headB;
16         while(currA != nullptr){
17             currA = currA->next;
18             m++;
19         }
20         while(currB != nullptr){
21             currB = currB->next;
22             n++;
23         }
24 
25         // 末尾对齐.
26         currA = headA;
27         currB = headB;
28         if(m > n){
29             int tmp = m - n;
30             while(tmp--){
31                 currA = currA->next;
32             }
33         }else{
34             int tmp = n - m;
35             while(tmp--){
36                 currB = currB->next;
37             }
38         }
39         while(currA != currB){
40             if(currA == nullptr)    return nullptr;
41             currA = currA->next;
42             currB = currB->next;
43         }
44         return currA;
45     }
46 };

142. 环形链表 II

快慢指针找到是否有环以及相遇位置。若没环则返回null

此时,设第一次入环位置为x,相遇位置距离x为y,再次到入环位置为距离为z

则慢指针走了x+y;快指针走了x+y+n(y+z)

同时快指针走了慢指针的两倍

则有2(x+y) = x+y + n(y+z)

=>x+y = n(y+z)

为了求x

则x = n(y+z) - y

=>x = n(y+z)-y-z+z

=>x = n(y+z)-(y+z)+z

=>x = (n-1)(y+z) + z

由于y+z是一个环,n是第n圈相遇,则说明 x = z

这时一个指针在相遇位置出发,另一个在起始位置出发,再次相遇的位置就是第一次相遇的点

 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         while(fast != nullptr && fast->next != nullptr){
15             fast = fast->next->next;
16             slow = slow->next;
17             if(fast == slow){
18                 // 一个指针在相遇节点处开始移动,同时在另一指针在头节点开始移动
19                 // 相遇位置就是第一次入环的位置
20                 fast = head;
21                 while(fast!=slow){
22                     fast = fast->next;
23                     slow = slow->next;
24                 }
25                 return fast;
26             }
27         }
28         return nullptr;
29     }
30 };