数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点...
題目:
給定一個單鏈表,只給出頭指針head:
1、如何判斷是否存在環?2、如何知道環的長度?
3、如何找出環的連接點在哪里?
4、帶環鏈表的長度是多少?
?
解法:
1、對于問題1,使用追趕的方法,設定兩個指針slow、fast,從頭指針開始,每次分別前進1步、2步。如存在環,則兩者相遇;如不存在環,fast遇到NULL退出。
2、對于問題2,記錄下問題1的碰撞點p,slow、fast從該點開始,再次碰撞所走過的操作數就是環的長度s。
3、問題3:有定理:碰撞點p到連接點的距離=頭指針到連接點的距離,因此,分別從碰撞點、頭指針開始走,相遇的那個點就是連接點。(證明在后面附注)
4、問題3中已經求出連接點距離頭指針的長度,加上問題2中求出的環的長度,二者之和就是帶環單鏈表的長度
bool IsExitsLoop(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; }
亦可以用類似與hash表的方法,即設立一個數組,將鏈表結點中的值做數組下標,當賦值沖突時就是環的接入點
證明題:
對于一個順時針的環,有P,Q兩點,且兩點相距為N,同時,P每向前移動一步,Q就向前以東兩步,已知環的周長是L,問P,Q兩點相遇在哪點上?如下圖所示:P點是環的入口點
假設P,Q兩點相遇時,P點移動的距離是X,則有以下等式:
X-N = 2*X - L;
=>X= L-N
那么我可以從上圖看到相遇點離入口點的距離為:L-(L-N)=N
假設單鏈表的總長度為L,頭結點到環入口的距離為a,環入口到快慢指針相遇的結點距離為x,環的長度為r,慢指針總共走了s步,則快指針走了2s步。另外,快指針要追上慢指針的話快指針至少要在環里面轉了一圈多(假設轉了n圈加x的距離),得到以下關系:
? ? s = a + x
? ? 2s = a + nr + x
? ? =>a + x = nr
? ? =>a = nr - x
由上式可知:若在頭結點和相遇結點分別設一指針,同步(單步)前進,則最后一定相遇在環入口結點
通過上面的證明題發現數學知識在編程世界中真的很重要呀~~
總結:我們看到這里面有一個核心的地方就是第一個問題,判斷有沒有環的情況,采用了兩個指針:快指針和慢指針,這個在處理一些鏈表的問題中尤其重要,比如下面的兩道關于鏈表的題目:
第一題:已知單鏈表的頭指針,查找到倒數第K個節點
這道題的通俗的解法就是先遍歷一邊鏈表,得到鏈表的長度N,然后再從頭開始遍歷N-K個節點即可
但是現在如果要求只遍歷一遍鏈表的話,該怎么操作呢?
這時候就可以借助快指針和慢指針了
我們定義一個快指針P和慢指針Q,先讓P指針走到K個節點位置,然后Q指針從頭指針開始和P一起移動,當P移動到尾部的時候,那么此時Q節點所在的位置就是倒數第K個節點。
第二題:已知單鏈表的頭結點,查找到鏈表的中間節點
這道題的通俗的解法和上面的方法一樣,就是先遍歷一邊鏈表,得到鏈表的長度N,然后再次遍歷N/2個節點即可
但是現在同樣的如果要求之遍歷一邊鏈表的話,該怎么操作呢?
這時候我們同樣可以借助快指針和慢指針了
我們定義一個快指針P和慢指針Q,P和Q同時從頭指針出發,快指針P每次移動兩步,慢指針每次移動一步,當快指針P到尾部的時候,慢指針Q所在的位置就是中間節點的位置。
通過上面的兩道題目我們可以看到快慢指針的在解決單鏈表的相關問題上還是很有用的~~
下面在來看一下還有一個技巧就是在解決第二道題目的時候,那個求環的入口節點,這個當時真的是沒有任何頭緒,所以這時候就要求我們又很好的數學功底了,能夠發現相關的規律,然后總結出定理,這樣就可以將問題簡化了。
轉載于:https://www.cnblogs.com/roccheung/p/5797333.html
總結
以上是生活随笔為你收集整理的数据结构和算法设计专题之---判断单链表中是否有环,环的长度,环的入口节点...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [信号处理技术]关于EMD的产生
- 下一篇: MySQL存储过程总结(二)