Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
对于循环链表的判断,应该都很清楚,就是通过快慢指针,判断是否会追赶上,但是如果需要找出循环链表的起始节点,就需要先搞清楚快慢指针相遇时的路程差。
假设链表起点为s,环的起始点为o,首次相遇点为m;设so = x, om =l ,环的长度为k,在首次相遇时,快指针走的路程是慢指针的一倍,且多走的部分为环长度的n倍。
则可得到如下公式 2(x+l) = x+l+nk => x+l = nk。从而可知如果一个节点从头结点往前走l,另一个节点从o点出发,最终会在o点相遇,也就类似于一个节点从s点,另一个节点在m点出发,最终会在o点相遇。
得代码如下:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The node where the cycle begins.
* if there is no cycle, return null
*/
ListNode *detectCycle(ListNode *head) {
// write your code here
ListNode *one = head, *two = head;
int c = 0;
int step ;
while(two){
one = one->next;
two = two->next;
if(two) two=two->next;
else return NULL;
c++;
if(one == two) {
step = c;
c = 0;
while(1){
c ++;
one = one->next;
two = two->next->next;
if(one == two){
int k = step / c;
one = head;
for(int i=0;i<(k-1)*c;i++){
one = one->next;
}
while(1){
one = one->next;
two = two->next;
if(one == two) return one;
}
}
}
}
}
return NULL;
}
};
或者:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The first node of linked list.
* @return: The node where the cycle begins.
* if there is no cycle, return null
*/
ListNode *detectCycle(ListNode *head) {
// write your code here
ListNode *one = head, *two = head;
while(two){
one = one->next;
two = two->next;
if(two) two=two->next;
else return NULL;
if(one == two) {
one = head;
while(one != two){
one = one->next;
two = two->next;
}
return one;
}
}
return NULL;
}
};