1. 程式人生 > >連結串列找環的起點

連結串列找環的起點

牛客網
思路:
1. 先使用快慢指標確定是否有環。原理
2. (1)方法1 如果有環,計算出環的長度,採用快慢指標,定位環起點
3. (2)方法2 如果有環,設定兩個指標從連結串列頭和快慢指標相遇點逐步前進,相遇點則是連結串列環起點。原理
方法一:

ListNode *detectCycle(ListNode *head) {
        ListNode *fast,*slow;
        fast = slow = head;
        while(fast&&fast->next&&fast->next
->next){ slow = slow->next; fast = fast->next->next; if(slow == fast) break; } if(!fast||!fast->next||!fast->next->next) return NULL; //尋找環的長度 ListNode *p; int count; p = slow; count = 1
; while(p->next!=slow){ p = p->next; count ++; } p = head; for(int i = 0;i<count;i++) p = p->next; ListNode *c = head; while(p!=c){ c = c->next; p = p->next; } return
c; }

方法二:

    ListNode *detectCycle(ListNode *head) {
        ListNode *fast,*slow;
        fast = slow = head;
        while(fast&&fast->next&&fast->next->next){
              slow = slow->next;
              fast = fast->next->next;
              if(slow == fast) break;
        }
        if(!fast||!fast->next||!fast->next->next) return NULL;
        //尋找環的長度
        fast = head;
        while(fast!=slow){
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }

分析:

  1. 為什麼通過判斷快慢指標是否相等可以判斷環是否存在
    假設連結串列路徑為:x + y,其中x為環之前的路徑長度,y為環之後的路徑長度
    慢指標追上快指標,則必然是在環中,無環只會差距越來越大。
    當快指標追上慢指標時有
    設fast: m,slow: n; (m,n分別為fast,slow指標移動的距離)

    {(mx)%y=(nx)%ym=2n
    =>[(n-x) + n]%y = (n-x) %y
    =>n是y的整數倍
    那麼n是一步一步走的,則n必然可以為n的整數倍。
    則通過判斷快慢指標是否相等可判斷是否有環
  2. 找到相遇點如何求環的起點
    連結串列圖
    設相遇為p,則劃分環為cd 兩段,c為已經走過的點,則
    x+c+k*(d+c) = 2*(x+c)
    => x = kd+(k-1)c
    => x = (k-1)(d+c) + c
    則設定兩個指標一個指向連結串列頭,一個指向相遇點,兩個每次前進一步,相遇點則是環的起點

參考:連結串列環起點