判斷單鏈表是否成環演算法

2021-08-09 05:22:53 字數 1896 閱讀 3666

演算法思想:定義兩個指標p, q,其中p每次向前移動一步,q每次向前移動兩步,所以就成p為慢指標,q為快指標。

那麼如果單鏈表存在環,則p和q進入環後一定會在某一點相遇,因為進入環後就會一直迴圈下去,否則q將首先遇到null,就說明不存在環。

這裡肯定會有人問,就是為什麼當單鏈表存在環時,p和q一定會相遇呢?

為了簡單說明,就直接假設單鏈表是環狀的(就如同操場上的跑道)。

情況一:p和q起點相同,看能否再次相遇。

第i次迭代時,p指向i mod n, q指向2i mod n

所以要i≡2i(mod n) => (2i - i) mod n = 0 => i mod n = 0 => 當i=n時

即當i=n時就再次相遇了

情況二:p和q起點不相同,看能否再次相遇。

假設q比p先走了k步, 0 < k < n

第i次迭代時,p指向i mod n , q指向(k + 2i) mod n

所以要i≡(2i+k)(mod n) => (i+k) mod n = 0 => 當i=n-k時

即當i=n-k時就再次相遇了

測試**

public

class

linklisttest

/*** 判斷乙個單鏈表是否成環

*@param head 單鏈表的頭結點

*@return

*/private

static

boolean

iscircle(node head)

//定義兩個指標為同一起點

node n1 = head; //慢指標

node n2 = head; //快指標

//只要有環的話,這個迴圈條件就絕對會滿足,如果沒有環的話,到了最後總不滿足

while(n2.next != null && n2.next.next != null)

}return

false;

}/**

* 構造乙個單鏈表

*@param length 長度

*@param iscircle 是否成環

*@param circlepos 環的起點位置

*@return 單鏈表的頭結點

*/private

static node getlinklist(int length, boolean iscircle, int circlepos)

node head = new node(0);

node last = head;

node circlenode = null;

//直接從1開始迴圈,因為0賦給了head

for (int i = 1; i < length; i++)

last.next = node;

last = node;

}if (iscircle && last != null)

return head;

}/**

* 結點類

*/private

static

class

node

public

node(int pos, node next)

public

intgetpos()

public

void

setpos(int pos)

public node getnext()

public

void

setnext(node next) }}

執行截圖

判斷單鏈表是否成環

成環 可以是迴圈單鏈表,即首位相連 也可以是部分成環,即尾部和其他節點相連。判斷是否成環 使用快慢指標遍歷鍊錶 慢指標 從頭節點開始,一次跳乙個節點。快指標 從頭節點開始,一次跳兩個節點。如果是成環的,這兩個指標一定會相遇。如上圖所示,藍色表示慢指標,紅色表示快指標,他們在經過4次遍歷後相遇,也就是...

經典演算法題 判斷單鏈表是否成環及尋找成環節點

判斷單鏈表是否成環是乙個計算機領域的經典演算法問題 如何通過程式判斷傳入的鍊錶是否存在環,並且求出環長度 成環點等問題 下面就是乙個存在環的單鏈表 最簡單的方法是建立乙個雜湊表,將每個節點的位址都儲存起來,如果某個節點的位址出現在了雜湊表中,那麼首次出現的那個節點就是我們要找的成環的起點了 1 示例...

判斷單鏈表是否有環

1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如果找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fast,slow 初始值都指向頭,slow每次前進一步,fast每次前進二步,如果鍊錶存在環,則fast必定先進入環,而slow後進入環,兩個指標必定相遇。當然,fas...