1. 程式人生 > 其它 >力扣141.環形連結串列

力扣141.環形連結串列

技術標籤:連結串列演算法資料結構leetcodejava

141. 環形連結串列

給定一個連結串列,判斷連結串列中是否有環。
為了表示給定連結串列中的環,我們使用整數 pos 來表示連結串列尾連線到連結串列中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該連結串列中沒有環。示例 1:

輸入:head = [3,2,0,-4], pos = 1
輸出:true
解釋:連結串列中有一個環,其尾部連線到第二個節點

示例2:

輸入:head = [1,2], pos = 0
輸出:true
解釋:連結串列中有一個環,其尾部連線到第一個節點。

示例 3:
輸入:head = [1], pos = -1
輸出:false
解釋:連結串列中沒有環。

思路一:雙指標法

 1 public class Solution {
 2     public boolean hasCycle(ListNode head) {
 3         // 快慢指標
 4         // 兩指標以不同的速度同時向後移動,如果在某個地方相遇了說明含有環
 5         ListNode slow = head, fast = head;
 6         while(true){
 7             if(fast == null || fast.next == null){
 8                 return false;
 9             }
10             slow = slow.next;
11             fast = fast.next.next;
12             if(slow == fast)
13                 break;
14         }
15         return true;
16     }
17 }

力扣測試時間為0ms, 空間為39.7MB

複雜度分析:

時間複雜度:我們根據慢指標所走過的路程來作為時間複雜度的估計,假設從連結串列頭結點到入環結點的結點個數為N1, 環的結點的個數為L,前N1的結點的時間是O(N1),下面討論慢指標在後L個結點上所花費的時間。

根據環形跑道相向的追及問題,如果兩個跑步者從同一起點出發,第一次相遇肯定是速度快著比速度慢者多跑了一圈,當兩人相遇時距離他們下次相遇所花費的時間是最大的(假設花費的時間為t),其他情況下距離他們的下次相遇時間都小於這個最大值,所以從現在開始到相遇,速度快者比速度慢者多跑的距離肯定小於一圈。

慢指標入環後,此時快指標已經在環上了,所以距離他們的下次相遇時間肯定小於等於t,所以從現在開始到相遇,快指標比慢指標多跑的距離肯定小於一圈,假設慢指標的速度為v,指標的速度為kv, 那麼kvt - vt <= L, 所以 vt<= L/(k-1), 又因為 k = 2, 所以 vt <= L, vt剛好是慢指標在環上經過的結點個數,所以慢指標入環後最多經過 L 個結點就會被快指標追上,所以慢指標從入環到相遇所花費的時間最大為O(L),所以總的時間為O(t) <= O(N1)+O(L) = O(n)

所以時間複雜度為O(n)

空間複雜度:O(1)

思路二:雜湊法

遍歷連結串列,遍歷過程中嘗試把結點放入集合中,對於每個結點,如果集合中已經存在該結點,說明存在環,返回true

 1 public class Solution {
 2     public boolean hasCycle(ListNode head) {
 3        ArrayList<ListNode> list = new ArrayList<>();    // 儲存結點
 4        for(ListNode node = head; node != null; node = node.next){
 5            if(list.contains(node)){ // 如果集合中已經存在該結點,說明存在環,返回true
 6                return true;
 7            }else{
 8                list.add(node);
 9            }
10        }
11        return false;
12     }
13 }

力扣測試時間為375ms, 空間為39.8MB(這個時間花費著實有點恐怖)

複雜度分析:

時間複雜度:遍歷了一次連結串列,所以時間複雜度為O(n),雖然複雜度是O(n), 但是力扣測試時間卻這麼大,應該是contains()函式的花費比較大,因為contains()不是紅黑樹儲存,所以查詢效率不是很高。

空間複雜度:空間花費主要是集合中元素的個數,最大為O(n)