一、思路
双指针
二、解题方法
首先创建一个哑节点dummy便于操作链表
然后创建两个指针slow和fast,开始时两个指针都指向dummy地址,fast先向前移动n+1个单位
然后同时操作slow和fast,利用fast移动到链表末尾的长度=slow移动到倒数n+1个位置的长度。
最后删除倒数第n个节点,使倒数第n+1个节点直接指向倒数第n个的后面一个节点。
三、code
/**
* 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) {
//通过创建名为 dummy 的节点对象,并将其初始化为值为 0 的节点,我们可以使用该节点作为链表的虚拟头结点。虚拟头结点不存储实际的数据,只用于方便操作链表,例如在删除头结点或者删除倒数第 n 个节点时,可以避免特殊处理。
ListNode dummy(0);
dummy.next=head;
ListNode* fast = &dummy;将虚拟头结点 dummy 的地址赋值给指针变量 fast。这样,fast 指针就指向了虚拟头结点 dummy
//通过将 fast 指针初始化为虚拟头结点 dummy 的地址,我们可以在后续的操作中使用 fast 指针来遍历链表,并且不会影响到真正的头结点 head。
ListNode* slow = &dummy;
for(int i=0;inext;
}
while(fast)// 同时移动 fast 和 slow 指针,直到 fast 到达链表末尾
{
fast=fast->next;
slow=slow->next;//此时,slow 指针指向的节点就是倒数第 n+1 个节点,即要删除节点的前一个节点。
}
// 删除倒数第 n 个节点,并更新 slow->next 指向删除节点的下一个节点。释放被删除节点的内存空间。
ListNode* toDelect=slow->next;
slow->next=slow->next->next;
delete toDelect;
return dummy.next;//返回虚拟头结点的下一个节点作为链表的新头结点
}
};
=========================================================================学到的知识:
①ListNode dummy(0);
是创建了一个名为 dummy
的节点对象,并初始化其值为 0。
②ListNode* fast = &dummy;
的作用是将指针 fast
初始化为指向虚拟头结点 dummy
的地址。