1. 程式人生 > >找出有環連結串列中環的起始節點

找出有環連結串列中環的起始節點

  給定一個有環的連結串列,寫一個演算法,找出環的起點。

例如:

輸入:A->B->C->D->E->C[與前面的C是同一個節點]

輸出:C

判斷一個連結串列是否存在環有一個簡單的方法,就是使用一個快指標、和一個慢指標,快指標每次走兩步,慢指標每次走一步,則如果有環,它們最後必然會相遇的。本題的難點在於要找出環的起點。其實也不難,與判斷是否有環類似,用兩個步長分別為1和2的指標遍歷連結串列,直到兩者相遇,此時慢指標走過的長度就是環的長度。另外相遇後把其中指標重新設定為起始點,讓兩個指標以步長1再走一遍連結串列,相遇點就是環的起始點。

證明也很簡單,證明如下:

我們注意到第一次相遇時

慢指標走過的路程S1 = 非環部分長度 + 弧A長

快指標走過的路程S2 = 非環部分長度 + n * 環長 + 弧A長

S1 * 2 = S2,可得 非環部分長度 = n * 環長 - 弧A長

讓指標A回到起始點後,走過一個非環部分長度,指標B走過了相等的長度,也就是n * 環長 - 弧A長,正好回到環的開頭。

ListNode *findcyclehead(ListNode *head){
  ListNode *mp=head;
  ListNode *kp=head;

  while(kp->next!=NULL && kp!=mp){
    kp=kp->next->next;
    mp=mp->next;
   }

   if(kp->next==NULL) return NULL;

   mp=head;
   while(kp!=mp){
    kp=kp->next;
    mp=mp->next;
   }
  return kp;
}