题目
🔗题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
给你一个链表,删除链表的倒数第 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 <= 300 <= Node.val <= 1001 <= n <= sz
进阶: 你能尝试使用一趟扫描实现吗?
思路
使用虚拟头节点,这样就不用单独处理头节点了。
使用快慢指针(双指针)。快指针先走 n 步,然后再走一步。然后快慢指针在快指针指向的元素不为空的时候一直往链表结尾走。当快指针指向空时,慢指针刚好走到要删除的节点的前一个节点。
代码
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
if (!head) return head;
const dummyHead = new ListNode(0, head);
let fast: ListNode | null = dummyHead;
let slow = dummyHead;
let step = n;
// 快指针先往前走 n 步
while (step > 0 && fast) {
fast = fast.next;
step--;
}
// step 大于 0, 说明 n 大于链表的长度,不用移除元素
if (step > 0) return dummyHead.next;
// 让 fast 再往后走一步,这时 slow 刚好指向要移除的元素的前一个元素
fast = (fast as ListNode).next;
// 当 fast === null 时,
// 慢指针刚好移动到要移除的元素的前一个元素
while (fast) {
// 这时 fast 移动到链表末尾
fast = fast.next;
slow = slow.next as ListNode;
}
slow.next = (slow.next as ListNode).next;
return dummyHead.next;
}