<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
目錄
連結直達:
題目:
正常的單連結串列每個節點順次連結,最後一個節點指向NULL,如下:
而帶環連結串列的最後一個節點不再指向NULL了,指向的是前面任意一個節點,以此形成帶環連結串列,並一直迴圈下去。如下:
我們可以將上述圖畫的抽象一點,在沒有進入環之前我們用直線表示,進入環之後用圈來表示,以此示意迴圈。此題需要用到我們之前講解的求中間節點和求倒數第k個節點的快慢指標的思想。定義兩個指標slow和fast均指向一開始的位置。 讓slow一次走一步,fast一次走兩步。
當slow走到直線一半的位置時,此時的fast剛好就在環的入口點。
假設slow剛好走到環的入口點時,fast走到如下位置,此時fast開始追趕模式
fast開始追趕slow,假設fast在如下的位置開始追上slow
程式碼如下:
bool hasCycle(struct ListNode *head) { struct ListNode*slow=head; struct ListNode*fast=head; while(fast&&fast->next) { slow=slow->next; fast=fast->next->next; if(slow==fast) { return true; } } return false; }
單純從解體的角度看,此題並不複雜,僅需用到快慢指標的思想即可解決,單是由此題可以引出多個值得我們探討的問題,以此來加深我們對環形連結串列的認知,如下三大拓展問題:
答案:一定能。
證明:
當slow走到中間的時候,fast一定進環了,此時fast開始追擊。我們假設slow進環以後,slow和fast的距離是N,此時slow走1步,fast走2步,它們倆的距離縮短1變為N-1。以此類推,每次追擊,距離縮小1,當距離縮小為0時就追上了。綜上,一定能追上。
答案:不一定
證明:
我們先來討論slow一次走1步,fast一次走3步的情況。假設slow走了1步,fast走3步時剛好進環,而當slow剛好進環的時候,fast可能已經走了1圈,具體情況得看環的大小,此時slow和fast之間的距離為N。並假設環的長度是C。
slow一次走1步,fast一次走3步,距離變為N-2。由此可見,fast和slow每走一次,距離縮短2。此時就不難發現了,需要分類討論,當N是偶數時,剛好可以追上,當N是奇數時,追到最後距離為-1,此時就要再追了,意味著slow和fast之間的距離變成C-1。
繼續追擊,根據前面的分析,如果C-1是偶數,那麼可以追上。如果C-1是奇數,那麼就永遠追不上了,將會無線迴圈追下去,可就是追不上。他們的差距N是由進環前的長度和環的長度決定的,而這兩個又都是隨機的,所以N的值不確定,可奇可偶,又像剛剛那樣討論下去,出現奇數將一去不復返。
同理fast一次走4步也是這樣的討論,同樣都是不一定,不過這個時候是每走一次,距離縮短3。當N是3的倍數就可以追上,當不是3的倍數就要繼續討論了,有興趣的童鞋可以繼續鑽研下去,思想和fast一次走3步一樣,這裡不過多贅述。
當我們搞清楚slow和fast分別走的距離時,入口點自然就明瞭了。
法一:
slow一次走1步,fast一次走2步,那麼fast走的距離是slow的2倍
在具體講解之前,首先要搞清楚,不存在說慢指標slow在裡頭走了一圈,快指標fast還沒有追到slow,因為fast每次走2步,slow每次走1步,它倆間的距離每次都縮小1,所以只會越來越近,直到追到。最多最多也就快1圈,但從來也不會剛好滿1圈。所以下面很容易推出slow和fast分別走了多少。
假設:
【連結串列頭 - - - 入口點】:L
【入口點 - - - 相遇點】:X
【環的長度】:C
slow走的距離:L + X
fast走的距離:L + N*C + X
解釋:
因為先前已經提到slow不會都走了一圈還沒被追到,所以很容易推出slow的距離就是L+X
而快指標一次走2步,很可能會因為環過小導致在slow指標進入入口點前,fast指標已經走了好幾圈。簡而言之3句話:
根據一開始說的,fast走的距離是slow走的距離的2倍,可列出如下式子:
2*(L+X) = L + N*C + X
化簡後:L+X = N*C 或 L = N*C - X 或 L = (N-1)*C + (C-X) 或 L + X = N*C
用此公式即可證明:一個指標從meet走,一個指標從head走,他們會在入口點相遇!
因為式子(N-1)*C表明從相遇點走了N-1圈後又回到了相遇點,此時再走C-X的距離就回到了入口點,由上得知,此公式確實讓它們回到了入口點。
用一道切實的題目來具體解出入口點的位置:
連結直達:
題目:
程式碼如下:
struct ListNode* detectCycle(struct ListNode* head) { struct ListNode* slow = head; struct ListNode* fast = head; while (fast && fast->next) { //判斷是否是帶環連結串列 slow = slow->next; fast = fast->next->next; if (slow == fast) { struct ListNode* meet = slow; while (meet != head) { //求出相遇點 meet = meet->next; head = head->next; } return meet; } } return NULL; }
求相遇點還有另外一種方法:
找到相遇點meet後,讓meet做尾,讓下一個點做新連結串列的頭
此法顯的尤為巧妙,剛好轉換成了兩個連結串列求交點的問題。因為此時headA連結串列的尾部是meet,而headB連結串列的尾部也是meet,此時就意味著倆連結串列必會相交,而相交的地方就是入口點,兩連結串列相交正是博主上篇博文中所詳細講解的,這裡就不過多強調了。
到此這篇關於C語言超詳細講解資料結構中單向環形連結串列的文章就介紹到這了,更多相關C語言 單向環形連結串列內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45