給定一個帶有頭結點 head 的非空單鏈表,返回鏈表的中間結點。如果有兩個中間結點,則返回第二個中間結點。
示例 1:
輸入:[1,2,3,4,5]
輸出:此列表中的結點 3 (序列化形式:[3,4,5])
返回的結點值爲 3 。 (測評系統對該結點序列化表述是 [3,4,5])。
示例 2:
輸入:[1,2,3,4,5,6]
輸出:此列表中的結點 4 (序列化形式:[4,5,6])
由於該列表有兩個中間結點,值分別爲 3 和 4,我們返回第二個結點。
方法一
思路:
cur:當前節點
i)先求出單鏈表的長度,然後得到單鏈表長度的一半。
ii)通過簡單的for循環。讓cur一個一個往下走,直到找到中間節點。
代碼如下:
class Solution {
public ListNode middleNode(ListNode head) {
int len = getLength(head)/2; //得到單鏈表長度的一半
ListNode cur = head; //讓當前節點從頭開始走
for (int i = 0;i < len;i++) {
cur = cur.next;
//for循環,讓cur一個一個往下走,直到找到中間節點
}
return cur;
}
public int getLength(ListNode head) {
int count = 0;
ListNode cur = head;
while(cur!= null) {
count++;
cur = cur.next;
}
return count;
}
}
分析:
這種方法簡單易懂,適合大部分人。但是不夠簡潔,還需要你單獨寫一個getLength()函數,不足以抓住面試官的眼球。
方法二
思路邏輯圖如下:
設定一個fast和slow分別從頭開始走
fast一次走兩步,slow一次走一步
當fast走到最後的時候,slow即是中間節點。
代碼如下:
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next; //fast一次走兩步
slow = slow.next; //slow一次走一步
}
return slow;
}
}
分析:
別出心裁,思維靈活,代碼簡潔。
綜上兩種方法,第一種通過簡單的for循環,簡而易懂,適合初學者;而第二種方法,別出心裁,思維靈活,可以借鑑參考此類解題思路。