感謝這個哥的總結。
問題:對於問題1、2、3,思考如何給出嚴謹的數學證明呢?
給定乙個單鏈表,只給出頭指標h:
1、如何判斷是否存在環?
2、如何知道環的長度?
3、如何找出環的連線點在**?
4、帶環鍊錶的長度是多少?
給定兩單鏈表a、b,只給出兩頭指標。請問:
5、如何判斷兩單鏈表(無環)是否相交?
6、如何判斷兩單鏈表(不知是否有環)相交?
7、如何尋找兩相交鍊錶(不知是否有環)的第乙個相交節點?
解法:1、對於問題1,使用追趕的方法,設定兩個指標slow、fast,從頭指標開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到null退出。
2、對於問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的運算元就是環的長度s。
3、問題3:有定理:碰撞點p到連線點的距離=頭指標到連線點的距離,因此,分別從碰撞點、頭指標開始走,相遇的那個點就是連線點。
該定理的證明可參考:
4、問題3中已經求出連線點距離頭指標的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度
判斷是否存在環的程式:
[cpp]view plain
copy
print?
bool i***itsloop(slist *head)
return !(fast == null || fast->next == null);
}
尋找環連線點(入口點)的程式:
[cpp]view plain
copy
print?
slist* findloopport(slist *head)
if (fast == null || fast->next == null)
return null;
slow = head;
while (slow != fast)
return slow;
}
5、如何判斷兩單鏈表(無環)是否相交?
有兩種可取的辦法:
(1)人為構環,將鍊錶a的尾節點指向鍊錶b,再判斷是否構環成功?從鍊錶b的頭指標往下遍歷,如果能夠回到b,則說明相交
(2)判斷兩鍊錶最後乙個節點是否相同,如果相交,則尾節點肯定是同一節點
6、如何判斷兩單鏈表(不知是否有環)相交?
先判斷是否有環,判斷是否有環可以使用追逐辦法,設定兩個指標,乙個走一步,乙個走兩步,如果能相遇則說明存在環
(1)兩個都沒環:回到問題1
(2)乙個有環,乙個沒環:不用判斷了,肯定兩鍊錶不相交
(3)兩個都有環:判斷鍊錶a的碰撞點是否出現在鍊錶b的環中,如果在,則相交。(相交時,環必定是兩鍊錶共有的)
7、如何尋找兩相交鍊錶(不知是否有環)的第乙個相交節點?
同樣,使用追逐辦法先判斷是否存在環,分情況討論
(1)無環:人為構環,將鍊錶a的尾節點指向鍊錶b,則構成乙個帶環的單鏈表。這個問題就轉換成尋找帶環單鏈表的環入口節點。
解法參考:
(2)有環:
這是本人[email protected]的思路:
於環是共有的,因此a與換的連線點可以認為是a、b的相交點,同理b也是。這樣就可以對a或者b單獨求鍊錶與環的連線點。
下面是原作者的思路:
計算出兩鍊錶的長度la、lb,(環的長度和環到入口點長度之和就是鍊錶長度)
計算帶環鍊錶長度,可參考
如果la>lb,則鍊錶a指標先走la-lb,然後鍊錶b指標開始走,兩者相遇的點就是相交點
如果lb>la,則鍊錶b指標先走lb-la,然後鍊錶a指標開始走,兩者相遇的點就是相交點
單鏈表的環相關問題
給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?證明 slow首次在a點進入環路時,fast一定在環中的b點某處。設此時slow距head長為x,b點距a點長度為y,環周長為s。因為fast和slow的步差為1,所以slow前行距離為y的時候,恰好會被fast在m點追上。因為y2 如何知道環...
單鏈錶環問題
給定乙個單鏈表,只給出頭指標h 1 如何判斷是否存在環?2 如何知道環的長度?3 如何找出環的連線點在 4 帶環鍊錶的長度是多少?5 如果存在環,求出環上距離任意乙個節點最遠的點 對面節點 6 擴充套件 如何判斷兩個無環鏈表是否相交 7 擴充套件 如果相交,求出第乙個相交的節點 解法 1 對於問題1...
單鏈表成環問題
思路一 新建乙個unordered set 思路二 兩個指標,乙個走得乙個走得慢,如果相遇了肯定是有環的,參考 思路一 class solution return false 思路二 include include include includeusing namespace std struct ...