LeetCode 2095:删除链表的中间节点
题目描述
给你一个链表的头节点 head 。删除 链表的 中间节点 ,并返回修改后的链表的头节点 head 。
长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点(下标从 0 开始),其中 ⌊x⌋ 表示小于或等于 x 的最大整数。
对于 n = 1、2、3、4 和 5 的情况,中间节点的下标分别是 0、1、1、2 和 2 。
解题思路
这题其实就是把 LeetCode 876:链表的中间结点 - 掘金 (juejin.cn) 和 删除链表结点结合起来。
思路一:利用快慢指针
设置快慢两个指针,快指针一次走两步,慢指针一次走一步,快指针走到终点,慢指针刚好走到中间,
再使用一个指针pre指针 时刻指向 slow 的前一个节点。这样我们就可以在遍历结束后,通过 pre 将 slow 删除了, 其中删除逻辑为pre.next = pre.next.next;
细节:
当链表中只有一个节点时,我们会删除这个节点并返回空链表。对这种情况, 直接返回空指针。
实现代码如下:
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteMiddle = function(head) {
if(head.next === null){
return null
}
var pre = new ListNode();
pre.next = head;
var fast = head, slow = head;
while(fast !== null && fast.next !== null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
// 删除链表的中间节点
pre.next = pre.next.next;
return head;
};
时间复杂度: O(n); fast指针需要遍历一次链表,因此最多走 n 步;
空间复杂度: O(1);
或者不使用pre记录, 使用一个dummy节点, 循环条件稍微不一样:
实现代码如下:
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteMiddle = function(head) {
if(head.next === null){
return null
}
var dummy = new ListNode(null, head);
var fast = dummy, slow = dummy;
while(fast.next !== null && fast.next.next !== null) {
slow = slow.next;
fast = fast.next.next;
}
// 删除链表的中间节点
slow.next = slow.next.next;
return head;
};