單鏈表中環的檢測(JAVA)

2021-09-12 11:46:17 字數 4509 閱讀 3699

參考單鏈表反轉中的主類**

假設乙個單鏈表是環形鍊錶,那麼該鍊錶的元素總數可分為兩部分

size = m + n

其中m是直線部分,n是環形部分

假想這是乙個跑道,從直線跑道為起點,之後進入環形跑道,然後一直繞著環形跑道跑

現在有兩個人一起從起點出發,速度不一致,快的速度為v,慢的速度為w,有v>w>0

假設兩人足夠有力量跑下去,那麼這兩人會不會在環形跑道的某點相遇呢?

經過時間t之後,如果滿足如下公式,則兩人可再次相遇

vt - wt = kn

其中k為整數

另一種說法就是:足夠時間後,跑快的人是否一定可以超跑慢的人正好整數圈呢?

答案是肯定的,n就算再大,也經不起足夠長的時間tv-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 ...