《程式設計之美》兩鍊錶相交及擴充套件詳解

2021-06-03 18:58:31 字數 2444 閱讀 8213

《程式設計之美》兩鍊錶相交及擴充套件詳解:

給定乙個單鏈表,只給出頭指標h:

1、如何判斷是否存在環?

2、如何知道環的長度?

3、如何找出環的連線點在**?

4、帶環鍊錶的長度是多少? 

解法:1、對於問題1,使用追趕的方法,設定兩個指標slow、fast,從頭指標開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到null退出。

2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。

3、問題3:有定理:碰撞點p到連線點的距離=頭指標到連線點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連線點。

設h走到c的長度為a,s走到p的長度為b,p走到的s長度為c。則相當於2個人從h節點開始,分別以1和2的速度走,相遇點為p,則第乙個人走的時間為h->s->p的時間(a+b),第二個人在該時間內走的距離則為2(a+b),而它走的路線為h->s->p->s->p,即比第乙個人多走了乙個環的長度,距離為(a+b+c+b)。則由2(a+b)= (a+b+c+b),可得a=c,即ps=hs,即證。

4、問題3中已經求出連線點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度。

判斷是否存在環的程式:

bool i***itsloop(slist *head) 

slist *slow = head, *fast = head; 

while ( fast && fast->next )  

slow = slow->next; 

fast = fast->next->next; 

if ( slow == fast ) break; 

return !(fast == null || fast->next == null); 

bool i***itsloop(slist *head)

slist *slow = head, *fast = head;

while ( fast && fast->next )

slow = slow->next;

fast = fast->next->next;

if ( slow == fast ) break;

return !(fast == null || fast->next == null);

尋找環連線點(入口點)的程式:

slist* findloopport(slist *head) 

slist *slow = head, *fast = head; 

while ( fast && fast->next )  

slow = slow->next; 

fast = fast->next->next; 

if ( slow == fast ) break; 

if (fast == null || fast->next == null) 

return null; 

slow = head; 

while (slow != fast) 

slow = slow->next; 

fast = fast->next; 

return slow; 

《程式設計之美》裡面有一篇是講如何判斷兩鍊錶是否相交,讀後覺得原文太過囉嗦。於是,筆者總結了一下,此類問題可以擴充套件為兩大類,分別是:

1、單鏈表與環問題

2、單鏈表相交與環問題(本文)

給定兩單鏈表a、b,只給出兩頭指標。請問:

1、如何判斷兩單鏈表(無環)是否相交?

有兩種可取的辦法:

(1)人為構環,將鍊錶a的尾節點指向鍊錶b,再判斷是否構環成功?從鍊錶b的頭指標往下遍歷,如果能夠回到b,則說明相交

(2)判斷兩鍊錶最後乙個節點是否相同,如果相交,則尾節點肯定是同一節點

2、如何判斷兩單鏈表(不知是否有環)相交?

先判斷是否有環,判斷是否有環可以使用追逐辦法,設定兩個指標,乙個走一步,乙個走兩步,如果能相遇則說明存在環

(1)兩個都沒環:回到問題1

(2)乙個有環,乙個沒環:不用判斷了,肯定兩鍊錶不相交

(3)兩個都有環:判斷鍊錶a的碰撞點是否出現在鍊錶b的環中,如果在,則相交。(相交時,環必定是兩鍊錶共有的)

3、如何尋找兩相交鍊錶(不知是否有環)的第乙個相交節點?

同樣,使用追逐辦法先判斷是否存在環,分情況討論

(1)無環:人為構環,將鍊錶a的尾節點指向鍊錶b,則構成乙個帶環的單鏈表。這個問題就轉換成尋找帶環單鏈表的環入口節點。

解法參考:

(2)有環:計算出兩鍊錶的長度la、lb,(環的長度和環到入口點長度之和就是鍊錶長度)

計算帶環鍊錶長度,可參考

如果la>lb,則鍊錶a指標先走la-lb,然後鍊錶b指標開始走,兩者相遇的點就是相交點

如果lb>la,則鍊錶b指標先走lb-la,然後鍊錶a指標開始走,兩者相遇的點就是相交點

程式設計之美 鍊錶相交問題

1 判斷兩個鍊錶是否相交 假設兩個鍊錶均不帶環 有四種方法 解法1 直觀的想法 判斷第乙個鍊錶的每個節點是否在第二個鍊錶中,這種方法的時間複雜度為o length h1 length h2 解法2 利用計數的方法 對第乙個鍊錶的節點位址進行hash排序,建立hash表,然後針對第二個鍊錶的每個節點的...

《程式設計之美》讀書筆記(十) 「鍊錶相交」擴充套件問題

感謝azuryy 提供 程式設計之美 3.6節 鍊錶相交 擴充套件問題答案 擴充套件1 鍊錶1 步長為1,鍊錶2步長為2 如果有環且相交則肯定相遇,否則不相交 list1 head p1 list2 head p2 while p1 p2 p1 null p2 null if p1 p2 p1 p2...

程式設計之美 判斷兩鍊錶是否相交

程式設計之美 裡面有一篇是講如何判斷兩鍊錶是否相交,讀後覺得原文太過囉嗦。於是,筆者總結了一下,此類問題可以擴充套件為兩大類,分別是 1 單鏈表與環問題 2 單鏈表相交與環問題 本文 給定兩單鏈表a b,只給出兩頭指標。請問 1 如何判斷兩單鏈表 無環 是否相交?有兩種可取的辦法 1 人為構環,將鍊...