链表处理 Part II
交换链表节点 删除节点 环形链表II
两两成对交换链表节点
24. 两两交换链表中的节点
0 1 2 3 4 … 0->2 2->1 1->3
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移动两位,准备下一轮交换
}
//leetcode官方 迭代算法 易理解一点
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* temp = dummyHead;
//循环条件: temp后紧跟两个节点
while (temp->next != nullptr && temp->next->next != nullptr) {
ListNode* node1 = temp->next;
ListNode* node2 = temp->next->next;
//更新temp后紧跟的两个节点的指针关系
temp->next = node2;
node1->next = node2->next;
node2->next = node1;
//移动两个节点
temp = node1;
}
return dummyHead->next;
}
删除链表的倒数第N个节点
法1: 链表长度 L 删除第L-N+1个节点指向的下一个节点
private:
//获取链表长度
int getListLen(ListNode* head){
int len=0;
while(head){
++len;
head = head->next;
}
return len;
}
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int L = getListLen(head);
ListNode* dummyHead = new ListNode(0,head);
ListNode* cur =dummyHead;
//x=Node(L-n+1) 为待删节点的前1个节点 [1~(x-1)]节点保持不变
for (int i = 1; i < L-n+1; ++i) {
cur =cur->next;
}
//跨过待删节点
cur->next =cur->next->next;
ListNode* ans = dummyHead->next;
delete dummyHead;
return ans;
}
法2:双指针
逆向思维
- 慢指针指向倒数第n+1个节点<->快指针指向正数第n+1个节点
- 整个链表的长度恒定:慢指针前移步数==快指针移动到最后null的步数
ListNode* dummyHead = new ListNode(0,head);
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
//提前向前移动n位
while(n-- && fast != NULL){
fast = fast->next;
}
fast = fast->next;
while(fast){
fast = fast->next;
slow = slow->next;
}
//指针指向被删节点的下一个节点
slow->next = slow->next->next;
ListNode* ans = dummyHead->next;
delete dummyHead;
return ans;
法3: 栈
未完待续
环形链表II
法1:双指针 快慢指针
思路
slow fast
v 1 2
L x+y x+n(y+z)
same time -> 2(x+y) =x+y+(n-1)(y+z)+z ->取 n=1 ->x=z
ListNode *slow = head, *fast = head;
while (fast != nullptr && fast->next != nullptr) {
//slow/fast v=1,2
slow = slow->next;
fast = fast->next->next;
//两个指针相遇 存在环 此时从head 和 相遇点,同时查找直至相遇
if (fast == slow) {
ListNode *ptr = head;
while (ptr != slow) {
ptr = ptr->next;
slow = slow->next;
}
return ptr;
}
}
return nullptr;
法2:哈希表
未完待续