定義乙個集合用來存放結點的引用,並將其初始化為空,從鍊錶的頭結點開始向後遍歷,每遍歷到乙個結點就判斷集合中是否有這個結點的引用,如果沒有,說明這個結點是第一次訪問,還沒有形成環,那麼將這個結點的引用新增到集合中去。如果在集合中找到了同樣的結點,那麼說明這個結點已經被訪問過了,於是就形成了環。這種方法的時間複雜度為o(n),空間複雜度也為o(n)。
定義兩個指標fast(快)與slow(慢),二者的初始值都指向煉表頭,指標slow每次前進一步,指標fast每次前進兩步,兩個指標同時向前移動,快指標每移動一次都要跟慢指標比較,如果快指標等於慢指標,就證明這個鍊錶是帶環的鍊錶。
如果單鏈表有環,那麼按照上述方法二的思路,當走得快的指標fast與走得慢的指標slow相遇時,slow 指標肯定沒有遍歷完鍊錶,而fast指標己經在環內迴圈了n圈 (n>=1)。如果slow 指標走了s步,則fast指標走了2s步,fast步數還等於s加上在環上多轉的n圈,假設環長為r,則滿足如下關係表示式:
2s = s +or
由此可以得到 : s=nr
設整個鍊錶長為l,入口環與相遇點距離為x,起點到環入口點的距離為a。則滿足如下關係表示式:
a+x=nr
a+x=(n-1)r+r=(n-l)r+l-a
a=(n-l)r+(l-ax)
(l-a-x)為相遇點到環入口點的距離,從煉表頭到環入口點的距離=(n-l)*環長+相遇點到環入口 點的長度,於是從煉表頭與相遇點分別設乙個指標,每次各走一步,兩個指標必定相遇,且相遇第一點為環入口點。將相遇點指標的前乙個節點的next域設成none即可解環。
# -*-coding:utf-8-*-
"""@author : 圖南
@software: pycharm
@time : 2019/9/6 15:28
"""class node:
def __init__(self, data=none, next=none):
self.data = data
self.next = next
# 構造單鏈表
def con_link(s, k):
head = node()
cur = head
nums = list(map(int, s.split(' ')))
k = int(k)
for num in nums:
node = node(num)
cur.next = node
cur = node
tmp = head
if k != 0:
for i in range(k):
tmp = tmp.next
cur.next = tmp
return head
# 列印單鏈表(用到方法一中的思想)
def print_link(head):
if head is none or head.next is none:
return none
flag =
cur = head.next
while cur:
if cur not in flag:
print(cur.data, end=' ')
cur = cur.next
else:
print(cur.data, end=' ')
break
print()
# 判斷鍊錶中是否有環
def isloop(head):
if head is none or head.next is none:
return none
fast = head.next
slow = head.next
while true:
try:
fast = fast.next.next
slow = slow.next
except exception:
print("該鍊錶中沒有環!")
print_link(head)
return false, head
if fast == slow:
print("該鍊錶中有環!")
print_link(head)
return true, fast
# 查詢環的入點口,並解環
def findloopnode(head, fast):
cur = head.next
pre = none
while cur != fast:
pre = fast
cur = cur.next
fast = fast.next
print(cur.data)
# 解環並列印鍊錶
pre.next = none
print_link(head)
if __name__ == '__main__':
nums = input('鍊錶:')
# 輸入環的入口點,若為0則鍊錶中無環
k = input('環的入點口:')
head = con_link(nums, k)
f, fast = isloop(head)
if f:
findloopnode(head, fast)
帶環單鏈表
無環單鏈表
帶環單鏈表及單鏈表的相交
帶環單鏈表的概念 當單鏈表的尾指標指向了鍊錶上任一非尾結點時,即生成了乙個帶環單鏈表。問題一 判斷是否帶環 通過快慢指標實現判斷,注意快指標必須是兩步,慢指標必須是一步,否則可能跨過 問題二 求環的入口點 通過數學思想,方法是使用一指標指向開頭,一指標指向環中的相交點,每次各走一步,如此所得相交點即...
帶環單鏈表求中點
首先,對於乙個n節點的單鏈環,如果給定乙個開始節點n0,然後用a,b兩個指標,分別以1和2的步長遍歷,那麼在a環了多少圈 m a距離n0有乙個怎麼樣的偏移量 offset 的情況下,a,b會重合呢?即指向同乙個節點。讓我們跳過費神的數學推導證明什麼的,先給出答案吧。在a走完一圈之後,a,b會回到n0...
單鏈表帶環問題
判斷單鏈表是否帶環?若帶環,求環的長度?求環的入口點?1 2 3 4 5 6 7 8 9 不帶環 鍊錶遍歷一次,到最後的節點的下乙個節點會指向null,此時鍊錶不帶環。帶環 在判斷鍊錶是否帶環之前,應該先判斷鍊錶是否為空。空鍊錶肯定不帶環。只要鍊錶帶環,對鍊錶進行遍歷就會形成死迴圈,沒有出口。這是就...