連結串列找環的起點
阿新 • • 發佈:2019-01-29
牛客網
思路:
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;
}
分析:
為什麼通過判斷快慢指標是否相等可以判斷環是否存在
假設連結串列路徑為:x + y,其中x為環之前的路徑長度,y為環之後的路徑長度
慢指標追上快指標,則必然是在環中,無環只會差距越來越大。
當快指標追上慢指標時有
設fast: m,slow: n; (m,n分別為fast,slow指標移動的距離)
{(m−x)%y=(n−x)%ym=2∗n
=>[(n-x) + n]%y = (n-x) %y
=>n是y的整數倍
那麼n是一步一步走的,則n必然可以為n的整數倍。
則通過判斷快慢指標是否相等可判斷是否有環找到相遇點如何求環的起點
設相遇為p,則劃分環為cd 兩段,c為已經走過的點,則
x+c+k*(d+c) = 2*(x+c)
=> x = kd+(k-1)c
=> x = (k-1)(d+c) + c
則設定兩個指標一個指向連結串列頭,一個指向相遇點,兩個每次前進一步,相遇點則是環的起點
參考:連結串列環起點