尋找單鏈表中的環的入口結點

2021-09-08 19:06:27 字數 3296 閱讀 1389

一,問題描述

給定乙個單鏈表,單鏈表中有環,請找出這個環的入口結點。比如,如下單鏈表:

入口結點是,結點4.

二,實現思路

如果僅僅是尋找入口結點,可以更改結點元素的值的話,只需要掃瞄一遍就可以找到入口結點了。

比如,假設所有的結點值都是正數,從頭開始,那麼在掃瞄過程中,將掃瞄的結點的值與 0 比較,如果不是0,則置為0;如果是0,則說明這個結點就是入口結點。

這種方式非常簡單高效,只需要掃瞄一遍鍊錶就可以找到入口結點了。缺點是:它修改了鍊錶中結點的值。

如果不允許修改結點的值,處理相對複雜一點。

1)假設單鏈表中的環有n個結點(在上面的示例圖中環有3個結點),可以設定兩個指標p1 和 p2,初始時,p1 和 p2 都指向表頭,指標p1 先在 鍊錶中移動 n 步,然後 p1 和 p2 再以相同的速度向前移動(每次向前移動乙個結點),當p2指向環的入口結點時,p1已經沿著環走了一圈又回到了入口結點。也即:當兩個結點相遇時,相遇時共同指向的這個結點就是環的入口結點。

2)那麼,現在的問題變成了:如何找出單鏈表中的環包含幾個結點?[參考:鐘錶的分針是如何追上時針的?]

比如,下面的單鏈表中的環包含了3個結點。

設定兩個指標 q1 和 q2,讓 q1 移動的速度是 q2 的兩倍,即:q1 每次移動兩個結點,q2 每次移動 乙個結點。

初始時,q1 和 q2 都指向頭結點,然後 q1 和 q2 開始移動,當 q1 再次 與 q2 相遇時,它們一定是在環中的某個結點上相遇的。

然後,再固定 q1 不動,讓 q2 遍歷鍊錶,並記錄它遍歷的結點個數。當 q2 再次與q1相遇時,它所遍歷的結點個數就是環中結點的個數了。

三,**實現

上面用到了單鏈表,因此得有結點的定義,這裡結點類以內部類實現。

public

class

entrynode

}private node head;//

頭結點//

other code.....

首先,得構造乙個帶環的單鏈表。通過insert()方法和 makeentry()方法來構造帶環的單鏈表。

//

採用頭插法,插入結點

public

void insert(int

ele)

}

insert()採用「頭插法」方式將結點插入到鍊錶中

/*

ele 就是入口結點的值

* 構造乙個帶環的鍊錶.如果 ele 不屬於鍊錶中的值,則丟擲illegalargumentexception

* point 用來遍歷鍊錶,prepoint記錄遍歷鍊錶時的前驅結點.

* 當 point.ele == ele時, 指定 當前 point 指向的結點作為 入口 結點

* * 然後 point 繼續遍歷,直到遍歷到尾結點. 然後最終由prepoint記錄尾結點, 並將尾結點的next指標指向入口結點

*/public

void makeentry(int

ele)

if(entry == null)//

ele does not in list, can not make a circle

throw

new illegalargumentexception(ele + " does not in list, can not make a circle");

prepoint.next = entry;//

prepoint is last node

}

makeentry()方法,負責讓單鏈表的表尾結點 的next指標 指向 鍊錶中的某個結點,從而構成了乙個環。

findentry()方法找出入口結點的值。整個完整**實現如下:

public

class

entrynode

}private node head;//

頭結點

//採用頭插法,插入結點

public

void insert(int

ele)

}/*ele 就是入口結點的值

* 構造乙個帶環的鍊錶.如果 ele 不屬於鍊錶中的值,則丟擲illegalargumentexception

* point 用來遍歷鍊錶,prepoint記錄遍歷鍊錶時的前驅結點.

* 當 point.ele == ele時, 指定 當前 point 指向的結點作為 入口 結點

* * 然後 point 繼續遍歷,直到遍歷到尾結點. 然後最終由prepoint記錄尾結點, 並將尾結點的next指標指向入口結點

*/public

void makeentry(int

ele)

if(entry == null)//

ele does not in list, can not make a circle

throw

new illegalargumentexception(ele + " does not in list, can not make a circle");

prepoint.next = entry;//

prepoint is last node

}

public

intfindentry()

return

next_k.ele;

}private

intcirclenumbers()

//now pre and next pointer all point same node

int circlenumber = 0;

circlenumber++;

next = next.next;//

next forward one step

while(next !=pre)

return

circlenumber;

}//hapjin test

public

static

void

main(string args) ;

for (int

ele : eles)

entrynode.makeentry(4);//

至此,構造完了乙個帶環的鍊錶

system.out.println("入口結點的值為: " +entrynode.findentry());

}}

原文:

判斷單鏈表是否存在環,尋找單鏈錶環的入口

判斷單鏈表是否存在環,如果存在環,找出環的入口 有乙個單鏈表,其中可能有乙個環,也就是某個節點的next指向的是鍊錶中在它之前的節點,這樣在鍊錶的尾部形成一環。問題 1 如何判斷乙個鍊錶是不是這類鍊錶?2 如果鍊錶為存在環,如何找到環的入口點?解答 一 判斷鍊錶是否存在環,辦法為 設定兩個指標 fa...

判斷單鏈表是否存在環及尋找環的入口點

單鏈表反 下面給出兩種可能的實現。普通版 void reverse node head head next null head pprev 遞迴版 node reverse node pnode,node head node temp reserve pnode next,head 遞迴 temp ...

判斷單鏈表是否存在環及尋找環的入口點

判斷乙個單鏈表是否存在環的解法如下 問題1 快慢指標何時相遇,是否迴轉幾十圈,才相遇呢?證明1 設環長為l,slow指標第一次進入環內,fast指標在前方的a節點處 0 0 x a 2x mod l 0 a x mod l 兩邊同時減去x 就是說a x對l求餘應該是0,即a x 0,l,2l 這一系...