前言
记录一下刷题历程 力扣第19题 删除链表第n个节点
删除链表第n个节点
原题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
分析
我们根据下面这张图来解释一下
我们让L指针指向第一个节点,L指针向右移动两次让R指针指向第三个节点此时让L指针和R指针同时向右移动直到右指针指向NULL我们发现此时左指针指向我们要删除的节点。但是如果我们要删除倒数第二个节点,我们应该让图中的3的next指向5,所以我们让左指针事先指向链表的头节点Head,右指针仍然指向3这个节点,此时我们发现同时移动左右指针,当右指针指向NULL时左指针指向3,也就是我们想要删除的节点的前一个节点,此时让该节点的next指向该节点next的next即可完成删除。
代码如下:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 创建一个虚拟头节点,方便处理删除头节点的情况
ListNode* dummy = new ListNode(0, head);
ListNode* left = dummy; // 初始化左指针为虚拟头节点
ListNode* right = head; // 初始化右指针为链表头
// 先让右指针前进 n 步
while(n && right) {
right = right->next;
n--;
}
// 同时移动左指针和右指针,直到右指针到达链表末尾
while(right) {
left = left->next;
right = right->next;
}
// 删除倒数第 n 个节点
left->next = left->next->next;
// 返回删除节点后的链表头(虚拟头节点的下一个节点)
return dummy->next;
}
};
解释注释
1.创建虚拟头节点:ListNode* dummy = new ListNode(0, head);
创建一个虚拟头节点 dummy,它的 next 指针指向原链表的头节点。这样做的好处是可以简化删除操作,包括删除头节点的情况。
2.初始化指针:
ListNode* left = dummy;:left 指针指向虚拟头节点。
ListNode* right = head;:right 指针指向链表的头节点。
3.移动右指针:
while(n && right):将 right 指针向前移动 n 步。
right = right->next;:每次移动一步,直到 right 指针前进了 n 步或者到达链表末尾。
4.同时移动左指针和右指针:
while(right):当 right 指针未到达链表末尾时,同时移动 left 和 right 指针。
这样,当 right 指针到达链表末尾时,left 指针正好在待删除节点的前一个节点。
5.删除目标节点:
left->next = left->next->next;:将 left 指针的下一个节点(即要删除的节点)跳过,从而删除该节点。
返回新链表头:
6.return dummy->next;:返回虚拟头节点的下一个节点,即删除目标节点后的链表头。
时间复杂度
因为只需要遍历一遍链表所以时间复杂度为O(n)。