對於鍊錶是否存在環,有三個問題需要考慮:
1. 是否有環
2. 入環節點
3. 環的長度
第一種方法快慢指標法,也稱之為龜兔演算法,設定兩個指標,慢指標和快指標。最開始均指向鍊錶的頭節點,之後,快指標每次後移兩個節點,慢指標每次後移乙個節點。
1. 如果快指標指向空,則鍊錶無環
2. 若快指標和慢指標再次指向乙個相同節點,則證明鍊錶有環
入環節點:
記快慢指標首次在節點i處相遇,即二者均指向節點i。令慢指標指向鍊錶的頭節點h,
之後,慢指標和快指標同時移動,每次後移乙個指標,第乙個相遇的節點就是環的起點。
環的長度,兩種方法:
法1. 求入環節點時,在慢指標指向煉表頭節點、快指標指向節點i時,設定整型變數length = 0, 之後直至快慢指標相遇,二者每同時移動一次,lenght增加1。相遇後,length + 1 即環的長度。
法2. 在快慢指標指向相同的節點i時,設定 length = 0, 快指標仍每次後移兩個節點,慢指標每次後移乙個節點,快慢指標同時移動後, length增加1。 快慢指標再次相遇時,length即為環的長度。
對於思路可以進一步參閱:
第二種方法: brent's algorithm
例子:python 實現**:
# python program to implement
# brent's cycle detection
# algorithm to detect cycle
# in a linked list.
# node class
class node:
# constructor to initialize
# the node object
def __init__(self, data):
self.data = data
self.next = none
class linkedlist:
# function to initialize head
def __init__(self):
self.head = none
# function to insert a new node
# at the beginning
def push(self, new_data):
new_node = node(new_data)
new_node.next = self.head
self.head = new_node
# utility function to prit
# the linked linkedlist
def printlist(self):
temp = self.head
while(temp):
print(temp.data, end=" ")
temp = temp.next
def detectcycle(self):
# if head is null
# then no loop
temp = self.head
if not (temp):
return false
first_p = temp
second_p = temp.next
power = 1
length = 1
# this loop runs till we
# find the loop. if there
# is no loop then second
# pointer ends at null
while (second_p and second_p != first_p):
# condition after which
# we will update the power
# and length as smallest
# power of two gives
# the start of cycle.
if (length == power):
# updating the power.
power *= 2
# updating the length
length = 0
first_p = second_p
second_p = second_p.next
length = length+1
# if it is null then no loop
if not (second_p):
return
# otherwise length stores
# actual length of loop.
# if needed, we can also
# print length of loop.
# print("length of loop is ")
# print (length)
# now set first_pointer
# to the beginning and
# second_pointer to
# beginning plus cycle
# length which is length.
first_p = second_p = self.head
while (length > 0):
second_p = second_p.next
length = length-1
# now move both pointers
# at same speed so that
# they meet at the
# beginning of loop.
while (second_p != first_p):
second_p = second_p.next
first_p = first_p.next
return first_p
# driver program for testing
llist = linkedlist()
llist.push(5)
llist.push(4)
llist.push(3)
llist.push(2)
llist.push(1)
# create a loop for testing
node = llist.head
while node.next:
node = node.next
node.next = llist.head.next
res = llist.detectcycle()
if(res.data):
print("loop found at ", end=' ')
print(res.data)
else:
print("no loop ")
第二種方法的優點在於:
1)在第乙個迴圈檢測是否存在環時, 也找到環的長度。
2)我們在每次迭代中只移動快指標,而避免移動第乙個指標,減少移動次數。
對於最開始提到的三個問題,對於入環的節點的思路 和 快慢指標方法中求環的長度的第一種處理思路 是共通的。
這裡是,已知環的長度,求入環節點,而快慢指標是已知環的節點求環的長度。 二者可以對比著看。
第三種做法:
遍歷鍊錶,將鍊錶的位址儲存在列表中,對於當前遍歷的節點,如果在列表中已經存在,則有環,且可以求出環的長度和入環節點。
如果鍊錶全部遍歷直至來鍊錶為空,則證明沒有環。
今天在看**的時候,偶然查到floyd's algorithm, 偶然看到這個問題。 10.10, 希望自己會更好。少無謂的道歉,多幾分滿意的感激。
如何判斷鍊錶是否有環
背景 例如在乙個大的系統中,如果出現兩個鍊錶相交的情況,而且釋放其中乙個鍊錶所有的節點,那就會造成資訊的丟失,並且釋放其中乙個鍊錶的所有節點,那就會造成資訊的丟失並且與之相交的鍊錶也會受到影響,如下圖 給出兩個單鏈表的頭指標 h1,h2 假設兩個鍊錶均不帶環 方法一 判斷第乙個鍊錶所有的節點是否在第...
如何判斷鍊錶是否有環
這個問題可以衍生出很多擴充套件性的問題 給定乙個單鏈表,1.如何判斷是否有環 2.如何知道環的長度 3.如何找到環的入口 4.整個鍊錶的長度是多少 相應的解法如下 問題1時後面所有問題的根問題,解決這個問題一般用到快慢指標,乙個fast指標,乙個slow指標,兩個指標同時指向單鏈表的頭結點,然後fa...
判斷鍊錶是否有環
1.如何判斷是否有環?如果有兩個頭結點指標,乙個走的快,乙個走的慢,那麼若干步以後,快的指標總會超過慢的指標一圈。2.如何計算環的長度?第一次相遇 超一圈 時開始計數,第二次相遇時停止計數。3.如何判斷環的入口點 碰撞點p到連線點的距離 頭指標到連線點的距離,因此,分別從碰撞點 頭指標開始走,相遇的...