參考單鏈表反轉中的主類**
假設乙個單鏈表是環形鍊錶,那麼該鍊錶的元素總數可分為兩部分
size = m + n
其中m
是直線部分,n
是環形部分
假想這是乙個跑道,從直線跑道為起點,之後進入環形跑道,然後一直繞著環形跑道跑
現在有兩個人一起從起點出發,速度不一致,快的速度為v
,慢的速度為w
,有v>w>0
假設兩人足夠有力量跑下去,那麼這兩人會不會在環形跑道的某點相遇呢?
經過時間t
之後,如果滿足如下公式,則兩人可再次相遇
vt - wt = kn
其中k
為整數
另一種說法就是:足夠時間後,跑快的人是否一定可以超跑慢的人正好整數圈呢?
答案是肯定的,n
就算再大,也經不起足夠長的時間t
,v-w
就算再小,只要是個正數,就一定能在某個時間t
後正好甩另乙個人正好整數圈
單鏈表中環的檢測就是利用了這個思想
public
boolean
iscircle()
// 相同的起跑線
singlylinkednode
faster = header, lower = header;
// 如果跑快的人到達了終點,說明這條跑道沒有環形部分
while
(faster != null && faster.
getnext()
!= null)
// 兩人未相遇則繼續跑(根據前邊的簡單說明,有環形部分則一定會在某時某刻相遇,沒有環形部分,則跑快的人肯定會先跑完,所以不會死迴圈)
}return
false
;}
假定單鏈表確實存在環,接下來看怎麼定位環的入口位置
在實現**中可以看到,假定跑快的人速度為2,跑慢的人速度為1。
即v=2, w=1
帶入上述公式vt - wt = kn
得
t = kn
現在來看下跑快的人和跑慢的人各跑了多遠
跑快的人:2kn
跑慢的人:kn
因為是在環上相遇,可計算出兩人剛才各在環上跑了多遠
跑快的人:2kn - m
跑慢的人:kn - m
現在暫時只考慮環上部分,他二人進入環形跑道的入口就是要定位的點,只要跑了整數圈就肯定還會回到改點。從二人已經在環上跑的路程來看,他們現在距離入口的距離相同,都是m
,正好是直線跑道的距離。
而如果現在讓剛才跑快的人休息,跑慢的人繼續按原速度w=1
跑,另外有乙個人從直線的起點也按w=1
開始跑,那麼他二人一定會在環的入口相遇
}回到剛才快慢二人在環上相遇,因為二人的速度差是1,所以同一起點出發,不會出現某時刻快的人超過慢的人的問題
v=2, w=1
這是個追及問題,經過時間t
後,快的人會正好超過慢的人一圈,即n
vt - wt = n
帶入求解t = n
所以t
就等於環的長度值
public
intcirclelength()
singlylinkednode
faster = start, lower = start;
int length =0;
while
(length ==
0|| faster != lower)
return length;
}
a -> b -> c -> d -> e -> f -> g
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g;
iscircle ? false
a -> b -> c -> d -> e -> f -> g -> a
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : a; index[8] : b; index[9] : c;
iscircle ? true
circle start node : a
circle length : 7
a -> b -> c -> d -> e -> f -> g -> b
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : b; index[8] : c; index[9] : d;
iscircle ? true
circle start node : b
circle length : 6
a -> b -> c -> d -> e -> f -> g -> c
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : c; index[8] : d; index[9] : e;
iscircle ? true
circle start node : c
circle length : 5
a -> b -> c -> d -> e -> f -> g - > d
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : d; index[8] : e; index[9] : f;
iscircle ? true
circle start node : d
circle length : 4
a -> b -> c -> d -> e -> f -> g -> e
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : e; index[8] : f; index[9] : g;
iscircle ? true
circle start node : e
circle length : 3
a -> b -> c -> d -> e -> f -> g -> f
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : f; index[8] : g; index[9] : f;
iscircle ? true
circle start node : f
circle length : 2
a -> b -> c -> d -> e -> f -> g -> g
index[0] : a; index[1] : b; index[2] : c; index[3] : d; index[4] : e; index[5] : f; index[6] : g; index[7] : g; index[8] : g; index[9] : g;
iscircle ? true
circle start node : g
circle length : 1
單鏈表中環的檢測
檢測環的常用方法為快慢指標方法。如果快慢指標相遇,則說明存在環,本文中將返回相遇結點的數值 如果快指標的next為空時,則說明不存在環。本文中慢指標一次移動乙個結點,快指標一次移動2個結點。1 帶環鍊錶的檢測 快慢指標 pnode iscircle pnode head else if null h...
單鏈表中環的檢測
常見的基本思路類似雙人賽跑 a比b跑得快,如果不存在環的話,當他們沿著同樣的道路跑步,a將永遠碰不到b 但如果是在操場跑的話,a則遲早會遇見b 實現 定義兩個指標,fast和slow,fast每次移動兩個結點,slow每次移動乙個結點,如果fast和slow相遇,則說明存在環,如果fast next...
Java單鏈表的實現
package com.handy.ds author handy 2012 3 15 class node public node int data,node next public class singlelinkedlist param head the head to set public ...