思路
想要删除某结点,就要找到这个结点的前一个结点,怎么找?
用fast指针先走出n+1步(因为我这加了一个虚拟头结点,如果直接从原链表头结点走就是n步),slow指针再开始走,此时双指针同时移动,直到fast指针移动到链表末尾,slow指向要删除结点的前一个结点。
==>只要快慢指针之间相差n个结点即可
步骤
创建虚拟头节点:首先创建一个虚拟头节点(dummy node),这个节点指向原始链表的头节点。这样做的目的是简化边界条件的处理,特别是当需要删除的是头节点时。
初始化双指针和计数器:设置两个指针,
slow
和fast
,都初始化为虚拟头节点。同时初始化一个计数器count
,用于记录fast
指针移动的次数。移动
fast
指针:开始遍历链表,每次移动fast
指针,并增加计数器count
。当count
小于等于n
时,继续移动fast
指针直到count
大于n
。同步移动
slow
和fast
指针:一旦fast
指针移动了n+1
步,开始同时移动slow
和fast
指针,直到fast
指针到达链表末尾。这样,slow
指针将位于倒数第n+1
个节点的位置。删除倒数第
n
个节点:由于slow
指针现在位于倒数第n+1
个节点,所以slow.next
指向的就是倒数第n
个节点。将slow.next
设置为slow.next.next
,从而移除倒数第n
个节点。返回结果:最后返回虚拟头节点的下一个节点,即处理后的链表头节点。
题目
解题示例代码
//定义链表节点类
function ListNode(val, next) {
this.val = (val===undefined ? 0 : val) // 如果val未定义,则默认为0
this.next = (next===undefined ? null : next) // 如果next未定义,则默认为null
}
var removeNthFromEnd = function (head, n) {
// 创建一个虚拟头节点,指向原链表的头节点
let node = new ListNode(0, head)
// 如果链表为空,直接返回原链表头节点
if (!node.next) return head
// 创建两个指针slow和fast,都指向虚拟头节点
let slow = node, fast = node
// 计数器,用于记录fast指针移动的次数
let count = 0
// 当fast指针不为null时,继续遍历链表
while (fast) {
// 当计数器小于等于n时,fast指针向前移动一位,计数器加1
if (count <= n ) {
fast = fast.next
count++
continue
}
// slow指针和fast指针同时向前移动一位
slow = slow.next
fast = fast.next
}
// 将slow指针的next指针指向其next指针的next节点,即移除倒数第n个节点
slow.next = slow.next.next
// 返回处理后的链表头节点(即虚拟头节点的next节点)
return node.next
};