面試題11:如何判斷單鏈表是否存在環


單鏈表有環的定義:鏈表的尾節點指向了鏈接中間的某個節點。

如下圖所示,如果有環,則遍歷到結點7時,又重新回到結點3,結點3就是環的入口結點。

 

思路:采用快慢指針的思想,設兩個工作指針,一個快一個慢,如果鏈表有環,它們必然會在某個結點處相遇。

功能函數:

/*     判斷鏈表是否有環    */
int hasLoop(Node *head)
{
    Node *p1,*p2;
    if(head == NULL || head->next == NULL) //鏈表為空,或是單結點鏈表直接返回頭結點
        return 0;
    p1 = p2 = head;
    while(p1->next != NULL && p1->next->next != NULL)
    {
        p1 = p1->next->next;
        p2 = p2->next;
        if(p1 == p2)
            return 1;
    }
    return 0;
}

這里需要注意一個問題,為什么快慢指針相遇就說明鏈表有環呢?該如何分析??

(以下內容來自:http://www.cnblogs.com/youxin/p/3303172.html

1.鏈表中是否有環的判斷

可以設置兩個指針(fast,slow),初始值均指向頭,slow每次向前一步,fast每次向前兩步;

如果鏈表中有環,則fast先進入環中,而slow后進入環中,兩個指針在環中必定相遇;

如果fast遍歷到尾部為NULL,則無環

2.鏈表有環,判斷環的入口點

  當fast若與slow相遇時,slow肯定沒有走遍歷完鏈表,而fast已經在環內循環了n圈(1<=n)。假設slow走了s步,則fast走了2s步(fast步數還等於s 加上在環上多轉的n圈),設環長為r,則:

2s = s + nr
s= nr

設整個鏈表長L,入口環與相遇點距離為x,起點到環入口點的距離為a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)

(L – a – x)為相遇點到環入口點的距離,由此可知,從鏈表頭到環入口點等於(n-1)循環內環+相遇點到環入口點

(L-a-x為相遇點到環入口點的距離,怎么理解,比如上面的,我們假設slow和fast在點3相遇,

啟動為1,環入口點 為2,相遇點為3,走了(L-a-x)長的距離后就回到了2點。

我們在起點和環相遇點各設置一個指針,每次各走一步,必定相遇。相遇一定在2點,為什么,

因而,可以在鏈表頭,相遇點分別設定一個指針,每次各走一步,兩個指針必定相遇,則相遇第一點為環入口點


 
  
  
  
  
  
  
  
  
  
  
  
  
 
 
 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM