問題描述
Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos
which represents the position (0-indexed) in the linked list where tail connects to. If pos
is -1
, then there is no cycle in the linked list.
Follow up:
Can you solve it using O(1) (i.e. constant) memory?
給定一個鏈表,判斷它是否有一個循環。
爲了在給定的鏈表中表示一個循環,我們使用一個整數pos來表示tail連接到的鏈表中的位置(0索引)。如果pos是-1,那麼鏈表中就沒有循環。
跟進:
你能用O(1)(即常數)內存來解決它嗎?
輸入: head = [3,2,0,-4], pos = 1 輸出: true
輸入: head = [1,2], pos = 0 輸出: true
輸入: head = [1], pos = -1 輸出: false
Python 實現
要判斷一個鏈表是否存在環,一種比較常用方法是定義兩個指針,一個走快點,一個走慢點,只要在某個時候,兩個指針重合了,說明鏈表存在環。嚴謹一點的描述是,我們可以定義兩個指針,一個每次只走一步,另一個一次走兩步,在指針沒有指向空,也就是沒有到達鏈表末尾前,出現兩個指針重合的情況,說明這個鏈表存在環。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
oneStep = head
twoStep = head
while twoStep != None and twoStep.next != None:
oneStep = oneStep.next
twoStep = twoStep.next.next
if twoStep != None and twoStep == oneStep:
return True
return False
可能有人看完代碼之後,會想如果前面的那個指針把步伐設置更大,是不是就能更快使得兩個指針重合,減少循環次數以節省時時間?這個想法有一定的道理,但是由於鏈表的長度是未知的,有可能當我們把移動更快的那個指針的步伐設置過大,即便鏈表存在環,這個指針每次都與另一個指針錯過,這樣子可能會導致更大的時間成本,甚至會錯過重合的機會,導致判斷錯誤。當然,指針步長的設置可以很有技巧,但討論起來就比較複雜了。以後有機會再深入探討一下。