D7 24. 两两交换链表中的节点 + 19. 删除链表的倒数第N个节点
24 两两交换链表中的节点(力扣:https://leetcode.cn/problems/swap-nodes-in-pairs/
条件:成对交换链表节点(而不是其中的值)剩余单数或null时退出,最后返回新head(空/单节点链表返回原head)
Tips:
- 由于可交换情景下需要指定原第二个节点为新头节点、空和单节点链表不需要更换头节点,所以使用虚拟头统一处理(虚拟头next指向原head且return 虚拟头next),把修改丢给后面的循环判断;
- 遍历指针只操作遍历和交换,所以需要定义另一个prevTail指针衔接变化后的两对节点;
- 交换时易混淆遍历和衔接指针的指向,建议使用first和second保证逻辑清楚,此外交换时修改的都是first或者second的next而非first本身地址,所以prevTail可以在交换后指向first不用担心地址丢失或者指向被修改的地址;
点击查看代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//虚拟头记住未来新head的地址,不管需不需要移位,最后return dummyhead->next即可
ListNode* dummyHead = new ListNode();
dummyHead->next = head;
//ListNode* dummyHead = head->next;
//遍历用指针
ListNode* current = head;
//衔接切换前后两对节点
ListNode* prevTail = dummyHead;
//非空链表、单节点链表、后续待处理的为偶数
while(current != nullptr && current->next != nullptr){
ListNode* first = current;
ListNode* second = current->next;
ListNode* nextCurrent = current->next->next;
//2->1
second->next = first;
//1->3
first->next = nextCurrent;
//让上组的结尾指向新头,链接两个组
prevTail->next = second;
//越过12从3开始
current = nextCurrent;
//这里prevend更新成上一对的新尾部(第一次循环里是1)
prevTail = first;
}
return dummyHead->next;
}
};
19 删除链表的倒数第N个节点(力扣:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
条件:删除倒数第n,返回head(存在空/单节点链表,但1 <= n <= 链表长度size)
Tips:
- 因为题目为倒数所以可能忽略了删除节点为head的情况,所以引入虚拟头;
- 删除倒数第(n)个所以要在它前一个停下,快指针在最后一个节点停下,所以快慢指针的gap为(n)而非(n+1),即倒数第(n-1)个节点和倒数第(1)个节点的距离;
点击查看代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
//虚拟头处理要删除节点为head时的情况
ListNode* dummy = new ListNode(0, head);
ListNode* slow = dummy;
ListNode* quick= dummy;
int gapCount = 0;
//移动quick指针保证和slow差距为n个节点
while( quick->next != nullptr && gapCount < n ){
quick = quick->next;
gapCount++;
}
//差距满足后同时移动直到quick在最后、slow在倒数第n个前一个
//空或单节点链表不会进入while,直接进行下面的删除
while( quick->next != nullptr ){
quick = quick->next;
slow = slow->next;
}
//删除
ListNode* toBeDelete = slow->next;
slow->next = slow->next->next;
delete toBeDelete;
ListNode* newHead = dummy->next;
delete dummy;
return newHead;
}
};
浙公网安备 33010602011771号