0019. 删除链表的倒数第 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]
提示:
- 链表中结点的数目为 sz
- 1 <= sz <= 30
- 0 <= Node.val <= 100
- 1 <= n <= sz
进阶:你能尝试使用一趟扫描实现吗?
思路
法一:
我们可以通过两次遍历链表来删除倒数第 N 个结点。第一次遍历用于计算链表的总长度,第二次遍历用于找到并删除目标结点。具体步骤如下:
- 创建一个虚拟头结点 dummy,并将其 next 指向链表的头结点 head。
- 定义一个辅助函数 countSize 来计算链表的长度。
- 计算出链表的总长度 totalLen。
- 计算出需要删除的结点在正序链表中的位置,即 totalLen - n。
- 使用一个指针 curr 从虚拟头结点开始遍历链表,直到到达需要删除结点的前一个结点。
- 修改前一个结点的 next 指针,跳过需要删除的结点。
法二:
我们可以使用双指针法来实现一次遍历删除倒数第 N 个结点。具体步骤如下:
- 创建一个虚拟头结点 dummy,并将其 next 指向链表的头结点 head。
- 初始化两个指针 fast 和 slow,均指向虚拟头结点 dummy。
- 让 fast 指针先移动 n + 1 步,这样 fast 和 slow 之间就相隔了 n 个结点。
- 同时移动 fast 和 slow 指针,直到 fast 指针到达链表的末尾。
- 此时,slow 指针正好指向需要删除结点的前一个结点。
- 修改 slow 指针的 next 指针,跳过需要删除的结点。
解答
法一:
/**
* 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:
int countSize(ListNode* head){
int count = 0;
while(head!=NULL){
count++;
head = head -> next;
}
return count;
}
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
int totalLen = countSize(head);
ListNode* curr = dummy;
for(int i=0;i<totalLen - n;i++){
curr = curr->next;
}
curr->next = curr->next->next;
ListNode* res =dummy->next;
delete dummy;
return res;
}
};
法二:
/**
* 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) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* fast = dummy;
ListNode* slow = dummy;
for(int i=0;i<=n;i++){
fast = fast->next;
}
while(fast!=NULL){
fast=fast->next;
slow=slow->next;
}
slow->next = slow->next->next;
ListNode* res = dummy->next;
delete dummy;
return res;
}
};
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let dummy = new ListNode(0,head);
let slow = dummy;
let fast = dummy;
for(let i =0;i<=n;i++){
fast = fast.next;
}
while(fast!== null){
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
};