# 链表的中间节点

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

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

示例 1:

img

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

示例 2:

img

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

提示:

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

# 方法 1:快慢指针

如果说我现在有链表如下,是奇数个。那么中间的节点就是 3

p2
p1
1	2	3	4	5	null

还有下面是偶数个的情况:

此时中间节点好像是 3,又好像是 4。但是题目要求是找靠右的 那么就是 4 了

p2
p1
1	2	3	4	5	6	null

此时让慢指针 p1 一次走一步,让快指针 p2 一次走 两步,下面是执行过程:

第一轮循环:p1 走一步,p2 走两步

		p2
	p1
1	2	3	4	5	null

没有走到头就重复该过程 p1 走一步,p2 走两步

				p2
		p1
1	2	3	4	5	null

此时 p2 的 next 为 nulll 了就停止,而现在 p1 所在的位置就是当前链表的中间节点了

这是奇数的情况,那偶数呢?

分析如下:

第一轮

		p2
	p1
1	2	3	4	5	6	null

第二轮

				p2
		p1
1	2	3	4	5	6	null

第三轮

						p2
			p1
1	2	3	4	5	6	null

此时 p2 本身就是 null 了就停止,而当前 p1 就是偶数个链表的中间节点了

总结

  • 每次 p1 一次走一步,p2 一次走两步。当 p2 的 next 或者 p2 的本身就是 null 时就停止移动,然后 p1 的当前位置就是中间节点

代码

public ListNode middleNode(ListNode head) {
        ListNode p1 = head;
        ListNode p2 = head;
        while(p2 != null && p2.next != null)
        {
          p1 = p1.next;
          p2 = p2.next.next;
        }
        return p1;
    }