题目
思路
- 我们要的做的事情就是让倒数第 k + 1 个节点的 next 跳过第 k 个节点指向第 k - 1 个节点
- 最暴力的解法就是先完整遍历一遍链表得到链表的长度,然后重新遍历,到达指定位置后删除节点,这样要遍历 n + n - k 次
- 我们尝试用双指针来解只需要遍历 n 次
- 我们先让第一、二个指针指向头节点,第二个指针向前走 k 步,然后两个指针一起遍历,当第二指针走到最后一个节点的时候,第一个指针指向的就是倒数第 k - 1 个节点,为什么?
- 因为第一个指针和第二指针的间隔距离始终保持着 k - 1
解法
class ListNode {
constructor(val, next) {
this.val = val
this.next = next
}
}
const head = new ListNode(1, null)
let node = head
// 初始化链表
for (let i = 2; i <= 6; i++) {
node.next = new ListNode(i, null)
node = node.next
}
function deleteKNode(head, k) {
let end = head,
start = head
for (let i = 1; i <= k; i++) {
end = end.next
}
while(end.next) {
end = end.next
start = start.next
}
start.next = start.next.next
return head
}
tips:这种情况无法处理删除头节点的情况,因为我们无法获取头节点前面的一个节点,我们的思路是去修改所要删除的节点的前一个节点的next
使用哨兵优化
function deleteKNode(head, k) {
const dummy = new ListNode(0, null) // 新增
dummy.next = head // 新增
let end = dummy,
start = dummy
for (let i = 1; i < k + 1; i++) {
end = end.next
}
while(end.next) {
end = end.next
start = start.next
}
start.next = start.next.next
return dummy.next // 改动
}
tips:这样其实就是让头节点变成哨兵节点,避免我们上面说的那种情况