【Leetcode 876 】链表的中间结点——快慢指针(单节点与双节点)

16 阅读1分钟

 题目

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

示例 1:

输入: head = [1,2,3,4,5]
输出: [3,4,5]
解释: 链表只有一个中间结点,值为 3 。

示例 2:

输入: head = [1,2,3,4,5,6]
输出: [4,5,6]
解释: 该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点。

提示:

  • 链表的结点数范围是 [1, 100]
  • 1 <= Node.val <= 100

 解答

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

/** 快慢指针,高效的时间复杂度(单数快指针) */
function middleNode1(head: ListNode | null): ListNode | null {
  // 没数据,直接返回
  if (!head || !head.next) return head;

  //   创建快慢指针,初始值都为头节点
  //   创建快指针,其一次走二步,将一直踩单数节点,如 1、3、5、7
  let fast: ListNode | null = head;
  //   创建慢指针,其一次走一步
  let slow: ListNode | null = head;
  while (fast && fast.next) {
    // 当快指针直到链表尾部时,慢指针正好到链表中间
    fast = fast.next.next;
    slow = slow!.next;
  }
  return slow;
}

/** 快慢指针,高效的时间复杂度(双数快指针) */
function middleNode(head: ListNode | null): ListNode | null {
  // 没数据,直接返回
  if (!head || !head.next) return head;

  //   创建快慢指针,快指针先指向下一个节点,将一直踩双数节点,如 2、4、6、8
  //   创建快指针,其一次走二步
  let fast: ListNode | null = head.next;
  let slow: ListNode | null = head;

  //   注意,此处不能判断 fast.next,因为快指针为双数节点
  // 当链表为  1 2 3 4 5 6 ,当快指针为6时,慢指针为3,但要求返回后面一个节点,所以要再进一次循环
  while (fast) {
    slow = slow!.next;
    fast = fast.next?.next as ListNode | null;
  }
  return slow;
}