對於鍊錶是否存在環,有三個問題需要考慮:
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, 希望自己會更好。少無謂的道歉,多幾分滿意的感激。
如何判斷兩個鍊錶是否有交點
首先,兩個鍊錶如果有交點它應該是y型的。分別遍歷兩個鍊錶,如果尾節點位址相同,則有交點 分別遍歷兩個鍊錶,計算兩鍊錶長度,長的為a,短的為b,讓長的鍊錶先走a b步,然後兩個鍊錶儀器走,走到同一位址處為交點。把兩個鍊錶放到兩個陣列中遍歷,位址相同為交點。如何判斷單向鍊錶是否有環 遍歷放到鍊錶中,直到...
如何判斷兩個單向鍊錶是否有相交,並找出交點
判斷兩個鍊錶是否相交 假設兩個鍊錶都沒有環 1 判斷第乙個鍊錶的每個節點是否在第二個鍊錶中 2 把第二個鍊錶連線到第乙個後面,判斷得到的鍊錶是否有環,有環則相交 3 先遍歷第乙個鍊錶,記住最後乙個節點,再遍歷第二個鍊錶,得到最後乙個節點時和第乙個鍊錶的最後乙個節點做比較,如果相同,則相交 如何判斷乙...
如何判斷兩個單向鍊錶是否有相交,並找出交點
深信服一道筆試 如何判斷兩個單向鍊錶是否有相交,並找出交點。題比較簡單,單向鍊錶有交點意思就是交點後的節點都是一樣的了。node findnode node phead1,node phead2 while p1 next null while p2 next null if p1 p2 else ...