【連結串列問題】單向連結串列判斷是否有環、求入環節點、求環長、求連結串列長度
阿新 • • 發佈:2018-12-30
目錄
題目
判斷一個單項鍊表是否有環,如果有環,返回入環節點的值,如果無環,返回-1.要求空間複雜度為O(1).
思路
空間複雜度如果沒有要求, 可以用雜湊表來判斷。
在空間複雜度為O(1)的情況下,環狀連結串列相關問題通常用快慢指標來輔助完成。
快指標從頭節點開始一次走兩步,慢指標從頭節點開始一次走一步。如果快指標為空或者快指標的next指標指向節點為空,則連結串列無環。
如果快指標和慢指標相遇,則連結串列有環。
在有環的情況下,我們找入環節點。
設環的周長為C,在相遇時,慢指標走的長度為
則快指標一定比慢指標多走(n = 0,1,2...) 的長度,
根據快慢指標的速度關係(快指標一次走兩步,慢指標一次走一步),在相遇的時刻,有
由上面三個式子可得.
快慢指標相遇後,讓快指標指向頭部,慢指標不動。快指標一次走一步,慢指標一次走一步。
當快指標走長度時,慢指標走長度,此時兩指標在入環節點處相遇。
程式碼實現
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) {} };*/ class ChkLoop { public: int chkLoop(ListNode* head) { // write code here if(head == NULL || head->next == NULL) return -1; ListNode *fast = head; ListNode *slow = head; while(fast!=NULL && fast->next!= NULL){//注意邊界條件 fast= fast->next->next; slow = slow->next; if(fast==slow){//有環,第一次相遇 fast = head;//fast指標到連結串列頭 while(fast!=slow){ fast = fast->next; slow = slow->next; } return fast->val; } } return -1; } };
注意點
1、邊界條件的處理,判斷快指標到達連結串列末尾的條件為fast == NULL || fast->next == NULL,因為在這兩種情況下fast都不能繼續往下走了。
2、函式開頭對明顯的空連結串列和只有一個節點的連結串列進行處理。
此題的其他變式
1、求單鏈表的環長
快慢指標第一次相遇後,繼續快指標一次兩步,慢指標一次一步,這樣就變成了追及問題。從第一次相遇時刻到到第二次相遇時刻,快指標走的長度比慢指標多一圈。
2、判斷有環單鏈表的長度
環長+頭結點到入環節點的長度(lenA)