给定一个带有头结点 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.
分析:
最直接、最先想到的方法肯定是先求出链表的长度,然后让链表从头开始向后走链表的一半长度,即可求出中间结点。但是这种方法需要遍历单链表两遍,下面我说的这种方法只需要遍历单链表一遍就能求出中间结点。
需要定义两个结点,slow和fast。让fast和slow同时向后走,只不过fast一次向后走两个结点,slow一次只走一个结点,当fast走完时,slow所指即为中间结点。可以类比跑步,400m的跑道,男生一步跑2米,女生一步跑0.5米,则当男生跑完400m时,女生只跑了200m也就是跑道的一半
代码:
public ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
//循环结束的条件是单链表遍历完,要注意的是还有fast.next != null这个条件
//因为fast一次走两个结点,如果fast.next为空的话,会出现单链表异常的情况,所以这里也要判断
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}