题目
给你单链表的头结点 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;
}