原題:
Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull
.
=>找到單向鏈表的環的起點,若沒有環,返回null
Follow up:
Can you solve it without using extra space?
=>能否不使用額外的空間。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
}
};
曉東分析:
看單向鏈表中是否存在環,曉東之前已經講過了。這篇文章主要講一下,如何找到這個環的起點,其實方法很簡單,就是在快慢指針相交的時候,把快指針移到開始,然後大家都以1步的步長開始運動,再次遇到的時候就是環的起點。如何來證明這個做法呢,曉東來簡單講解一下。假設如下圖:
我們假設快慢指針相會於C點。這個時候他們走過的路程:
快指針路程=慢指針路程+N*圓的周長=AB的距離+BC距離+M*圓的周長(M和N都是整數,不一定相等)
而我們知道快指針的路程,其實是慢指針路程的兩倍。
也就是說:
快指針路程=2*慢指針的路程
所以2*慢指針的路程=慢指針路程+N*圓的周長
所以,慢指針路程=N*圓的周長。
代入上式得到:
2*N圓的周長=AB的距離+BC距離+M*圓的周長
所以AB的距離+BC距離=L*圓的周長
所以AB的距離= L*圓的周長-BC距離。
因此,我們從C點開始的慢指針,和從A點開始的慢指針肯定會相遇於B點。
代碼實現:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(head == NULL || head->next == NULL) return NULL;
ListNode *fast = head->next->next;
ListNode *slow = head->next;
while(fast != slow && fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
if(fast == NULL || fast->next == NULL)
return NULL;
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
};
運行結果:
16 / 16test cases passed.
|
Status:
Accepted |
Runtime: 68 ms
|
希望大家有更好的算法能夠提出來,不甚感謝。
若您覺得該文章對您有幫助,請在下面用鼠標輕輕按一下“頂”,哈哈~~·