1. 程式人生 > >Leetcode 141:環形連結串列(最詳細的解法!!!)

Leetcode 141:環形連結串列(最詳細的解法!!!)

給定一個連結串列,判斷連結串列中是否有環。

進階:
你能否不使用額外空間解決此題?

解題思路

一個最簡單的做法就是將連結串列反轉,我們看連結串列反轉後有什麼問題,關於連結串列反轉可以看這篇Leetcode 206:反轉連結串列(最詳細解決方案!!!)

1 -> 2 -> 3 -> 4 -> 5
       ^         |
       |         v
       ___________

我們開始反轉連結串列

1 <- 2 <- 3*<- 4 <- 5
       |         ^
       v         |
       ___________

我們看反轉到3,現在不會停止,而是會繼續

1 <- 2 -> 3 <- 4 <- 5
       |         ^
       v         |
       ___________

最後就變成了

1 -> 2 -> 3 <- 4 <- 5
|      |         ^
head    v         |
      ___________

此時我們發現又回到了起點處,所以我們最後只要判斷返回的節點是不是head,就可以判斷是不是有環。

class Solution(object):
    def
reverseList(self, head): pre = None cur = head while cur != None: lat = cur.next cur.next = pre pre = cur cur = lat return pre def hasCycle(self, head): """ :type head: ListNode :rtype: bool """
if head != None and head.next != None\ and self.reverseList(head) == head: return True return False

這個問題還有一個非常棒的解法,就是使用快慢指標。我們建立兩個指標,一個slow一個fast,我們令移動速度關係為 V f a s t = 2 V s l o w V_{fast}=2*V_{slow} ,我們假設環的長度為 V s l o w t i m e V_{slow}*time 的倍數k,如果此時slowfast都在環內的話,那麼在一定時間內兩者必定可以相遇(使用相對速度很好理解)。

class Solution(object):
    def hasCycle(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if head == None:
            return False
        
        fast, slow = head, head
        while fast.next != None and fast.next.next != None:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True

        return False

reference:

https://leetcode.com/problems/linked-list-cycle/discuss/44498/Just-reverse-the-list

https://leetcode.com/problems/linked-list-cycle/discuss/44489/O(1)-Space-Solution

我將該問題的其他語言版本新增到了我的GitHub Leetcode

如有問題,希望大家指出!!!