1. 程式人生 > >【leetcode】Linked List Cycle II,判斷連結串列是否有環

【leetcode】Linked List Cycle II,判斷連結串列是否有環

本題意思是無修改的判斷一個連結串列是否具有環,並且返回環的初始節點,否則返回NULL。
一種方法是對已經訪問到的節點設定一些標誌,比如將next指標指向某一個特定節點,或者其他方法等。這樣的問題是會對連結串列進行修改。另一種方法是採用兩個指標在連結串列上滑動,一個指標每次只滑過一個節點,另一個指標每次滑過兩個節點,連個指標同時從起點開始滑動。可以證明,當存在環時,兩個指標會在某次相遇在同一個節點,否則,快的指標會先到達NULL。
針對本題,本文對兩種方法都實現了。第一種方法最後需要將next的修改又改回原來值。而第二種方法是在判斷具有環後正確找出環的初始節點。當兩個指標相遇後,固定一個指標不動,另一個指標繼續滑動,每次滑動一個節點並計數,當再次相遇時,可得到環具有的節點數n。然後使兩個指標指向頭結點,當其中一個指標先於另一個指標n個節點後同時同步(每次滑動一個節點)滑動。由於兩個指標距離等於環具有的節點數n,那麼他們必然在環初始節點處相遇,這樣就找到了環初始節點了。
程式碼如下:

//using inplace marks
    ListNode* func(ListNode* head,ListNode* tag)
    {
       if(head==NULL)return NULL;
        if(head->next == tag )
        {
            return head;
        }
        ListNode *p=head->next;
        head->next = tag;
        ListNode* ret=func(p,tag);
        head->
next = p; return ret; } ListNode *detectCycle(ListNode *head) { ListNode* tag = new ListNode(0); if(head==NULL) { return NULL; } ListNode* p = head->next; head->next = tag; ListNode* ret = func(p,tag); head->
next = p; return ret; } //using fast and slow pointers ListNode *detectCycle(ListNode *head) { ListNode *fast=head,*slow=head; while(fast!=NULL&&slow!=NULL) { fast = fast->next; if(fast == NULL) return NULL; //if doesn't has a cycle,then fast reach the end before the slow. fast = fast->next; slow = slow->next; if(fast==slow) break; } if(fast!=NULL) // if has a cycle { int n=1; // n is the number of nodes in the cycle. fast = fast->next; while(fast!=slow) { ++n; fast=fast->next; } //Then we let two pointers begin from the front,and one begins after the another n nodes, //so that they can meet at the node where cycle begins. fast=head,slow=head; while(n>0) { fast = fast->next; --n; } while(fast!=slow) { fast=fast->next; slow=slow->next; } return fast; } else { return NULL; } }