引用说明
文档讲解:代码随想录
两两交换链表中的节点 (LeetCode24)
思路:需要三步,看图理解
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
dummyHead->next = head; // 将虚拟头结点指向head,这样方便后面做删除操作
ListNode* cur = dummyHead;
while(cur->next != nullptr && cur->next->next != nullptr) {
ListNode* tmp = cur->next; // 记录临时节点
ListNode* tmp1 = cur->next->next->next; // 记录临时节点
cur->next = cur->next->next; // 步骤一
cur->next->next = tmp; // 步骤二
cur->next->next->next = tmp1; // 步骤三
cur = cur->next->next; // cur移动两位,准备下一轮交换
}
return dummyHead->next;
}
};
删除链表的倒数第N个节点(LeetCode19)
思路:双指针,两个指针间隔N个位置,第一个指针遍历到尾巴,第二个指针就是倒数第N个位置。
ListNode* removeNthFromEnd(ListNode* head, int n) { ListNode* dummyhead = new ListNode(0); dummyhead->next = head; ListNode* cur = dummyhead; int count = 0; while(cur->next != NULL){ count++; cur = cur->next; } cur = dummyhead; for(int i = 0; i < n; i++){ if(i > count)return NULL; cur = cur->next; } ListNode* p = dummyhead; while(cur->next != NULL){ p = p->next; cur = cur->next; } ListNode* temp = p->next; p->next = p->next->next; delete temp; return dummyhead->next; }
链表相交 (面试题 02.07)
思路:首先找到两个链表的总长度,然后将其中一个长的链表移到和短的链表长度相等的位置,同时遍历两个链表,知道指向的位置相同。
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { int countA = 1; int countB = 1; ListNode* A = headA; ListNode* B = headB; //判A的长度 while (A->next != NULL) { countA++; A = A->next; } //判B的长度 while (B->next != NULL) { countB++; B = B->next; } A = headA; B = headB; if(countA >= countB){ for(int i = 0; i < (countA - countB); i++){ A = A->next; } }else{ for(int i = 0; i < (countB - countA); i++){ B = B->next; } } while(A != B){ A = A->next; B = B->next; } return A; }
环形链表II (LC142)
在推理过程中,大家可能有一个疑问就是:为什么第一次在环中相遇,slow的 步数 是 x+y 而不是 x + 若干环的长度 + y 呢?
即文章链表:环找到了,那入口呢? (opens new window)中如下的地方:
首先slow进环的时候,fast一定是先进环来了。
如果slow进环入口,fast也在环入口,那么把这个环展开成直线,就是如下图的样子:
可以看出如果slow 和 fast同时在环入口开始走,一定会在环入口3相遇,slow走了一圈,fast走了两圈。
重点来了,slow进环的时候,fast一定是在环的任意一个位置,如图:
那么fast指针走到环入口3的时候,已经走了k + n 个节点,slow相应的应该走了(k + n) / 2 个节点。
因为k是小于n的(图中可以看出),所以(k + n) / 2 一定小于n。
也就是说slow一定没有走到环入口3,而fast已经到环入口3了。
这说明什么呢?
在slow开始走的那一环已经和fast相遇了。
那有同学又说了,为什么fast不能跳过去呢? 在刚刚已经说过一次了,fast相对于slow是一次移动一个节点,所以不可能跳过去。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
if (slow == fast) {
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2; // 返回环的入口
}
}
return NULL;
}
};