Day4
注意虚拟头节点的引入和使用。在链表中引入虚拟头节点可以允许我们对head节点也进行一般化处理,而不用对头节点的状态进行特判。
24. Swap Nodes in Pairs
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* fake = new ListNode(-1);
fake->next = head;
ListNode* curr = fake;
while(curr->next && curr->next->next)
{
ListNode* next3 = curr->next->next->next;
ListNode* next1 = curr->next;
curr->next = curr->next->next;
curr->next->next = next1;
next1->next = next3;
curr = curr->next->next;
}
head = fake->next;
delete fake;
return head;
}
};
19. Remove Nth Node From End of List
- 移除倒数N个节点,依然使用假头方便我们定位位置
- 让
fast
指针先走n步后slow
再出发,slow
停止的时候正好就是待删除节点的前序节点
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* fake = new ListNode(-1);
fake->next = head;
ListNode* slow = fake;
ListNode* fast = fake;
int cnt = n;
while(cnt > 0)
{
fast = fast->next;
--cnt;
}
while(fast && fast->next)
{
fast = fast->next;
slow = slow->next;
}
ListNode* toDelete = slow->next;
slow->next = slow->next->next;
delete toDelete;
head = fake->next;
delete fake;
return head;
}
};
160. Intersection of Two Linked Lists
- 已知两个链表可能相交,只要分别计算两个链表的长度
- 假设两链表在某处相交,两链表相交后相同长度为x,则它们分别的长度则是
(a+x)
和(b+x)
- 假设两链表在某处相交,两链表相交后相同长度为x,则它们分别的长度则是
- 比较a和b,了解哪一个链表长度更长,并计算
abs(a-b)
- 通过双指针再次遍历链表,通过上一步计算的差,让双指针指向相同的位置
- 如果
a≥b
:先让指向链表A的节点提前走abs(a-b)
步 - 否则让指向B的节点先走
abs(a-b)
步
- 如果
- 双指针依次遍历并检查指针是否相同,判断相交
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = 0;
ListNode* curr = headA;
while(curr)
{
curr = curr->next;
++lenA;
}
int lenB = 0;
curr = headB;
while(curr)
{
curr = curr->next;
++lenB;
}
ListNode* currA = headA;
ListNode* currB = headB;
int gap = abs(lenB - lenA);
// std::cout << lenA << " " << lenB;
if(lenB >= lenA)
{
while(gap > 0)
{
currB = currB->next;
--gap;
}
}
else
{
while(gap > 0)
{
currA = currA->next;
--gap;
}
}
while(currA)
{
if(currA == currB)
return currA;
else
{
currA = currA->next;
currB = currB->next;
}
}
return nullptr;
}
};
142. Linked List Cycle II
- 链表求环的变体,不仅要检测环,还要找到环的入口
- 利用快慢指针,分别每次走一步和两步
- 如果指针没有相交
(fast != slow)
,fast
走到nullptr
→ 没有环存在 - 如果指针相交
(fast == slow)
,说明有环存在- 使用第三个指针从
head
出发,和slow
一块前进,每次一步。两者下一次相遇的位置就是环的入口
- 使用第三个指针从
- 如果指针没有相交
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == nullptr || head->next == nullptr)
return nullptr;
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
ListNode* tmp = head;
while(tmp != slow)
{
tmp = tmp->next;
slow = slow->next;
}
return tmp;
}
}
return nullptr;
}
};