参考链接
http://www.cnblogs.com/x1957/p/3406448.html
题目描述
Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
题目分析
这个题目不仅要求出是否有环,而且还需要指出环开始的结点。
看了各中分析,找出一个最简单的大牛的,这里我讲一下思路
使用快慢指针,快指针是慢指针的2倍速度
假设在红色凸起的地方相遇了。
F走的路程应该是S的两倍
S走的路程S = x + y
F走的路程F = x + y + z + y = x + 2y + z
2*S = F
2x+2y = x + 2y + z
得到x = z
上面是大神的说明,我认为有一个地方需要改动一下
我认为更合理的应该是F = x + (y + z)*k + y (k=1,2....n)
假设x特别长,环特别小,可以s到达环之前f已经在环里转了好多圈了
所以2*S=F
x + (y + z)*k + y = 2(x + y)
x = (y + z)*k -y = (y + z)*(k -1)+z
不过以上改动不影响算法
在相遇的时候,把slow置为head,fast速度改为1。这时slow从head,fast从相遇的地方开始一起移到。
这时我们会发现当slow起了x时。fast走了(y+z)*(k-1)+z,不难理解,他们会在环开始的地方相遇。
总结
return NULL;
ListNode *slow = head;
ListNode *fast = head;
while(fast->next != NULL && fast->next->next != NULL)
{
slow = slow->next;
fast = fast->next;
fast = fast->next;
if(fast == slow) //第一次相遇后,跳出
break;
}
//把slow置到head,fast速度改为1
slow = head;
while(fast->next != NULL && fast->next->next != NULL)
{
if(fast == slow) //这里需要移动前面,因为相遇的可能就是头结点
return slow;
slow = slow->next;
fast = fast->next;
}
注意两个while循环里的区别
代码
/*
编译环境CFree 5.0
*/
#include
#include
using namespace std;
struct ListNode{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
} ;
void printList(ListNode *head,char *name)
{
printf("%s\n",name);
while(head != NULL)
{
printf("%3d,",head->val);
head = head->next;
}
printf("\n");
}
class Solution {
public:
ListNode* detectCycle(ListNode *head) {
if(head == NULL)
return NULL;
ListNode *slow = head;
ListNode *fast = head;
while(fast->next != NULL && fast->next->next != NULL)
{
slow = slow->next;
fast = fast->next;
fast = fast->next;
if(fast == slow) //第一次相遇后,跳出
break;
}
//把slow置到head,fast速度改为1
slow = head;
while(fast->next != NULL && fast->next->next != NULL)
{
if(fast == slow) //这里需要移动前面,因为相遇的可能就是头结点
return slow;
slow = slow->next;
fast = fast->next;
}
return NULL;
}
};
ListNode* listCreate(vector
&list, int arr[], int n)
{
if(n <= 0)
return NULL;
for(int i=0;i
next = &list[i];
head = head->next;
}
head = &list[0];
return head;
}
//有环
void test0()
{
vector
list;
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
ListNode *head = listCreate(list,arr, 10);
printList(head,"head");
list[9].next = &list[3];//制造一个环
Solution so;
if(so.detectCycle(head) != &list[3])
printf("------------------------failed\n");
else
printf("------------------------passed\n");
}
//无环
void test1()
{
vector
list; int arr[10] = {0,1,2,3,4,5,6,7,8,9}; ListNode *head = listCreate(list,arr, 10); printList(head,"head"); //list[9].next = &list[3];//制造一个环 Solution so; if(so.detectCycle(head) != NULL) printf("------------------------failed\n"); else printf("------------------------passed\n"); } void test2() { vector
list; int arr[2] = {0,1}; ListNode *head = listCreate(list,arr, 2); printList(head,"head"); list[1].next = &list[0];//制造一个环 Solution so; if(so.detectCycle(head) != &list[0]) printf("------------------------failed\n"); else printf("------------------------passed\n"); } int main() { test0(); test1(); test2(); return 0; }