LeetCode 19. 删除链表的倒数第 N 个结点 TypeScript 实现
核心思路:快慢双指针 + 虚拟头结点,一趟遍历完成删除,统一处理删除头结点的边界场景。
typescript
/**
- Definition for singly-linked list.
*/
class ListNode {
val: number
next: ListNode | null
constructor(val?: number, next?: ListNode | null) {
this.val = (val === undefined ? 0 : val)
this.next = (next === undefined ? null : next)
}
}
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
// 虚拟头结点:统一处理删除头结点的特殊情况
const dummy = new ListNode(0, head);
let fast: ListNode | null = dummy;
let slow: ListNode | null = dummy;
// 快指针先走 n 步 for (let i = 0; i < n; i++) { fast = fast!.next; } // 快慢指针同步前进,直到快指针走到最后一个节点 while (fast!.next !== null) { fast = fast!.next; slow = slow!.next; } // 删除慢指针的下一个节点(倒数第 n 个) slow!.next = slow!.next!.next; return dummy.next;}
复杂度分析
- 时间复杂度:O(L),L 为链表长度,仅单次遍历链表
- 空间复杂度:O(1),只使用常数级别的指针变量
关键细节
- 虚拟头结点 dummy:避免单独判断「删除头结点」的边界情况,所有删除操作逻辑统一。
- 快慢指针间距:快指针先走 n 步,最终慢指针恰好停在待删除节点的前驱节点,直接修改 next 完成删除。
- 非空断言:题目保证 n 合法有效,因此使用 ! 断言非空,简化代码。
边界用例验证
- 单节点链表 [1] , n=1 → 返回 null
- 双节点删头 [1,2] , n=2 → 返回 [2]
- 双节点删尾 [1,2] , n=1 → 返回 [1]