原文連接: https://wangwei.one/posts/jav...
前面,咱們實現了 刪除單鏈表倒數第N個節點 操做,本篇來聊聊,如何求一個鏈表的中間節點。html
Leetcode 876. Middle of the Linked List
給定一個非空的單鏈表,要求返回它的中間節點,若是中間節點有兩個則返回第二個。java
例如:算法
Input: [1,2,3,4,5] Output: Node 3 from this list
Input: [1,2,3,4,5,6] Output: Node 4 from this list
第一種解法的思路比較容易想獲得,先計算出鏈表的總長度,再計算出中間節點的下標,而後得遍歷獲得對應的節點便可。數據結構
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode middleNode(ListNode head) { if(head == null){ return null; } int len = 0; for(ListNode curr = head; curr != null; ){ len++; curr = curr.next; } int targetIndex = 0; ListNode target = null; for(ListNode curr = head; curr != null; ){ if(targetIndex == len / 2){ target = curr; break; } targetIndex++; curr = curr.next; } return target; } }
第二種解法,使用快慢指針,讓快指針的移動速度是慢指針的兩倍,等到快指針到達終點時,慢指針剛好抵達中間節點。post
一段小路上,A車行駛的速度是B車的兩倍,等到A車到達終點時,B車剛好達到小路的中間位置。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode middleNode(ListNode head) { if(head == null){ return null; } ListNode slow = head; ListNode fast = head; for(ListNode curr = slow; slow != null; ){ if(fast == null || fast.next == null){ break; }else{ fast = fast.next.next; } slow = slow.next; } return slow; } }
到目前爲止,咱們已經使用快慢指針解決三個單鏈表相關的問題了:this
單鏈表環檢測刪除單鏈表倒數第N個節點spa
求鏈表的中間結點指針
解法三也比較巧妙, 遍歷單鏈表,只有當下標爲奇數時,指針才向前移動,到最後,指針所指即爲中間節點。code
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode middleNode(ListNode head) { if(head == null){ return null; } ListNode target = head; int index = 0; for(ListNode curr = head; curr != null; ){ if(index % 2 == 1){ target = target.next; } index++; curr = curr.next; } return target; } }
以上三種解法的時間複雜度均爲O(n),在leetcode上的運行時間爲 1ms,超過 82.96%
。htm