資料結構與演算法 | Leetcode 876. middle-of-the-linked-list

wangwei_hz發表於2019-01-24

資料結構與演算法 | Leetcode 876. middle-of-the-linked-list

原文連結:wangwei.one/posts/java-…

前面,我們實現了 刪除單連結串列倒數第N個節點 操作,本篇來聊聊,如何求一個連結串列的中間節點。

求連結串列的中間結點

Leetcode 876. Middle of the Linked List

給定一個非空的單連結串列,要求返回它的中間節點,如果中間節點有兩個則返回第二個。

例如:

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;
    }
}
複製程式碼

解法二

第二種解法,使用快慢指標,讓快指標的移動速度是慢指標的兩倍,等到快指標到達終點時,慢指標恰好抵達中間節點。

一段小路上,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;        
    }
}
複製程式碼

到目前為止,我們已經使用快慢指標解決三個單連結串列相關的問題了:

單連結串列環檢測

刪除單連結串列倒數第N個節點

求連結串列的中間結點

解法三

解法三也比較巧妙, 遍歷單連結串列,只有當下標為奇數時,指標才向前移動,到最後,指標所指即為中間節點。

程式碼

/**
 * 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%

相關練習

參考資料

相關文章