LeetCode 2095:删除链表的中间节点

237 阅读2分钟

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;
};

参考资料

2095. 删除链表的中间节点 - 力扣(LeetCode)