# 删除链表的倒数第N个节点 (opens new window)
- 难度:Medium
- 标签:链表 快慢指针
# 刷题思路
- [x] 先计算长度,再删除节点(两轮遍历)
- [x] 双指针间隔n步推进(一轮遍历)
# 方法 1 先计算长度,再删除节点(两轮遍历)
- 复杂度:
- 时间 O(N). 一轮遍历计算长度,一轮遍历删节点.
- 空间 O(1). 原地操作.
- 结果:
- 执行用时:84 ms, 在所有 JavaScript 提交中击败了70.03%的用户
- 内存消耗:39.8 MB, 在所有 JavaScript 提交中击败了5.03%的用户
var removeNthFromEnd = function(head, n) {
let [len, curr] = [0, head]
while (curr) [len, curr] = [len+1, curr.next] // 计算长度
const newHead = new ListNode(null)
newHead.next = head
let prev = newHead // prev最终将到达待删除节点的前一个节点
let [target, count] = [len-n, 0] // 计算目标位置
while (count < target) { // 推进直到到达目标位置
[prev, count] = [prev.next, count+1]
}
prev.next = prev.next.next // 删除逻辑, 前节点的next指向"被删除节点"的下一个节点
return newHead.next
};
# 方法 2 快慢指针间隔n步推进(一轮遍历)
- 复杂度:
- 时间 O(N). 一轮遍历解决.
- 空间 O(1). 原地操作.
- 结果:
- 执行用时:76 ms, 在所有 JavaScript 提交中击败了88.35%的用户
- 内存消耗:38.5 MB, 在所有 JavaScript 提交中击败了13.26%的用户
var removeNthFromEnd = function(head, n) {
const newHead = new ListNode(null)
newHead.next = head
let [prev, curr] = [newHead, newHead] // prev 最终将到达待删除节点的前一个节点
for (let i=0; i<n; i++) curr = curr.next // 推进 curr 直到比 prev 领先 n 个节点
while (curr.next) { // curr.next 存在时,两个指针继续推进
prev = prev.next
curr = curr.next
}
prev.next = prev.next.next // curr.next 不存在时,prev.next 即倒数第 n 个节点, 删之
return newHead.next
};
JS刷题记录 Leetcode-js (opens new window) 每周都会更新刷题心得或者题解, 你的点赞或 star 都将助力我产出更好内容~