解題筆記(30) 找含單鏈表的環入口點

2021-05-27 18:01:17 字數 1237 閱讀 8821

問題描述:有乙個單鏈表,其中可能有乙個環,也就是某個節點的next指向的是鍊錶中在它之前的節點,這樣在鍊錶的尾部形成一環。如果鍊錶存在環,找到環的入口點?

思路:這道題的原型可能來自《c專家程式設計》一書,題目為」怎樣才能檢測到鍊錶中存在迴圈「,書中給出的最終演算法是定義兩個指標p1,p2,p1每次移動乙個位置,而p2每次移動兩個位置,這樣如果鍊錶中存在迴圈,那麼p2一定能追上p1。如果不存在,那麼p2會到達鍊錶尾部,即檢測到空。這個比較簡單,但是如果要求找出環的入口點呢?

本文給出兩種思路。第一種需要輔助空間,可以用雜湊表,用來存放結點的位址。定義乙個指標用來遍歷鍊錶,假設指標當前指向 i 結點,檢查雜湊表中是否含有該結點,如果有則該結點就是環的入口點。否則,將該結點的位址加入雜湊表中。如果鍊錶不存在環,那麼最終會到達鍊錶末尾,從而跳出迴圈。實現中,由於標準庫中沒有hash,因此用集合代替,意思差不多。時間複雜度上會有影響,用雜湊表為o(n),而用集合為o(nlogn),而空間複雜度為o(n)。

第一種方法需要o(n)的輔助空間,如果要求輔助空間為o(1),應該怎麼辦呢?容易想到的就是用窮舉法,對於每個結點,檢查該結點是否是環的入口點。可定義兩個指標,p1和p2。p1每次往前移動一步,表示當前被檢查的結點。p2每次從頭部開始往前移動,當p1和p2相等時,檢查兩個指標通過的距離,如果距離一樣,表示該結點不是環入口點,距離不一樣,表示p1已經在環中繞了一圈,第二次到達入口點,而p2是第一次到達入口點,此時兩者所指的結點即為環的入口點。這種方法的時間複雜度為o(n^2),空間複雜度為o(1)。

是否存在時間複雜度為o(n),空間複雜度為o(1)的演算法呢?等待某位網友的解答。

參考**:

//函式功能 : 找含單鏈表的環入口點

//函式引數 : phead指向鍊錶首部

//返回值 : 返回的是環的入口點,如果不存在環,返回null

listnode* findfirstcrossnode_solution1(listnode * phead)

return pnode;

}

listnode* findfirstcrossnode_solution2(listnode * phead)

p2 = p2->next; //前進乙個位置

pos2++; //記錄走過的距離

} p1 = p1->next;

pos1++;

} return null;

}

判斷單鏈表是否有環及找環的入口

使用快慢指標,找到相遇節點 然後乙個指標指向頭節點,乙個指向相遇節點,一步步走直到兩個指標指向同乙個節點 即為環的入口點 include using namespace std typedef struct nodenode,linklist bool i istsloop linklist l r...

單鏈表的環入口,環大小,解環

1.單鏈表是否有環 使用快慢指標,都從head出發,慢指標一次一步,快指標一次兩步,如果兩個指標相遇,說明鍊錶有環,否則,快指標為null或其next為null,到達末尾節點 function hascircle head return fast null fast.next null 2.單鏈錶環...

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

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