資料結構與演算法 | Leetcode 141:Linked List Cycle

wangwei_hz發表於2019-01-04

pexels-photo-589810

前面,我們實現了連結串列的 反轉 操作,本篇來聊聊,如何檢測單連結串列中的環。

連結串列環檢測

Leetcode 141: Linked List Cycle

有兩種方法來解決這個問題:

使用Hashing

思路

定義一個Map,當迴圈遍歷Linked List時,依次將Node放入Map中,等到迴圈到下一輪時,檢查Node是否存在於Map中,若存在則表示有環存在。

實現

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    public boolean hasCycle(ListNode head) {
        Map map = new IdentityHashMap();
        for(ListNode x = head; x != null;){
            if(map.containsKey(x)){
                return true;
            }
            map.put(x, null);
            x = x.next;
        }
        return false;
    }
}
複製程式碼

Floyd判圈演算法

Floyd判圈演算法

如果有限狀態機、迭代函式或者連結串列上存在環,那麼在某個環上以不同速度前進的2個指標必定會在某個時刻相遇。同時顯然地,如果從同一個起點(即使這個起點不在某個環上)同時開始以不同速度前進的2個指標最終相遇,那麼可以判定存在一個環,且可以求出2者相遇處所在的環的起點與長度。

從Linked List的Head節點出發,我們定義兩個移動指標,一個的移動速度為每次前進一個節點,另一個每次前進兩個節點。然後判斷這兩個指標移動後的結果是否相等。

程式碼

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    
    public boolean hasCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){
                return true;
            }
        }
        return false;
    }
}

複製程式碼

這兩種方式的時間複雜度均為O(n),空間複雜度均為O(1).

參考資料

相關文章