1.如何判斷是否有環?
與返回鏈表倒數第k個節點的問題類似,定義兩個結點指針,一個走的快,一個走的慢,那麼當快的那個指針追上慢的指針時,說明鏈表帶環。
2.如何計算環的長度?
從第一次相遇(超一圈)時開始計數,第二次相遇時停止計數,返回的這個計數即爲環的長度。
3.如何判斷環的入口點:碰撞點到連接點的距離等於頭指針到連接點的距離,因此,分別從碰撞點、頭指針開始走,相遇的那個點就是連接點。
上述是一個簡單的計算過程:
(1)當fast與slow相遇時,show肯定沒有走完鏈表,而fast已經在還裏走了n(n>= 1)圈。假設slow走了s步,那麼fast走了2s步。fast的步數還等於s走的加上環裏轉的n圈,所以有:2s = s + nr。因此,s = nr。
(2)設整個鏈表長爲L,入口據相遇點X,起點到入口的距離爲a。因爲slow指針並沒有走完一圈,所以:
a + x = s,帶入第一步的結果,有:a + x = nr = (n-1)r + r = (n-1)r + L - a;即:a = (n-1)r + L -a -x;
//判斷鏈表是否帶環
int isLoop(PNode pHead)
{
PNode fast = pHead;
PNode slow = pHead;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow)
break;
}
if(fast == NULL || fast->_pNext == NULL)
return 0;
else
return 1;
}
//計算環的長度
int loopLength(PNode pHead)
{
if(!isLoop(pHead))
return 0;
PNode fast = pHead;
PNode slow = pHead;
int length = 0;
int flag1 = 0;
int flag2 = 0;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow && !flag2)
break;
if(fast == slow && flag2)
{
flag1 = 1;
flag2 = 1;
}
if(flag1)
++length;
}
return length;
}
//找到環的入口
Node* findLoopEntrance(PNode pHead)
{
PNode fast = pHead;
PNode slow = pHead;
while(fast != NULL && fast->_pNext != NULL)
{
fast = fast->_pNext ->_pNext ;
slow = slow->_pNext ;
if(fast == slow)
break;
}
if(fast == NULL || fast->_pNext == NULL)
return NULL;
slow = pHead;
while(slow != fast)
{
slow = slow->_pNext ;
fast = fast->_pNext ;
}
return slow;
}