结论:定义快慢指针,快指针一次走2步,满指针一次走1步,如果链表带环,他们会在环中某个位置相遇,如果不带环,快指针则会为空或者走到尾(奇数个结点,偶数个结点)
1、为什么slow走1步,fast走2步,他们会相遇?会不会错过?请证明
1.fast先进环,slow走了入环距离的一半。
2.slow进环,fast已经在环中走了一段,具体在哪和圆环的大小有关系
不管是大于slow还是小于slow,等于就正好相遇,他们都会有一个小于圆周长C的距离N,
再根据slow一次走1步,fast一次走2步,每次他们之间的距离N都减小1
每追1次,他们的距离变化:N
N-1
N-2
...
2
1
0
0意味着他们相遇了
2、为什么slow走1步,fast走n步(n>=3),他们会相遇?会不会错过?请证明
假设slow进环的时候fast和slow距离为N
fast走3步,slow走1步,他们每追一次距离会缩小2
那么他们的距离变为就是:N (N是偶数) N (N是奇数)
N-2 N-2
N-4 N-4
... ...
4 3
2 1
0 追上了 -1 这一次追不上 ->相当于距离变成C-1,相当于进入新的一轮追击
如果C-1是奇数,那么下一次还是会变成C-1,那么就永远
追不上了 如果C-1是偶数,那么就可以追上
关于N-3 或者N-某值,他们最后会剩下几取决于 例如:N-3 某数%3 范围只有0~2,那么也就是如果不是3的倍数,只能是0,1,2
不管fast走几步,slow走几步,他们之间每次追击,只要令距离每次-1,就可以追上,例如:slow每次走2步,fast每次走3步,也是一样每次距离减少1,也可以追上,N不是奇数就是偶数,每次减1,总能追上
附上代码:
bool hasCycle(struct ListNode *head)
{
struct ListNode *fast=head,*slow=head;
while(fast && fast->next)//奇数个节点和偶数个节点如果不带环 结束条件的不同
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
return true;
}
return false;
}
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
结论:如果有环,一个指针从快慢指针相遇点开始走,另一个指针从链表头开始走,都是一次走1步,他们最终会在入环点相遇
根据判断链表是否带环中,快慢指针走过的距离关系,快指针走的距离是满指针走过的距离的2倍
可以证明会在入环点相遇
假设
起始点-入口点的距离: L
入口点-相遇点的距离: X 0<=X<C
环的长度: C
当fast和slow相遇时
slow走过的距离是: L + X
fast走过的距离是: L+NC+X
关于X ,X永远是小于环的长度,并且X == N
X == N 再没相遇之前fast和slow的距离是N,也就是说他们还要再追N次,而slow每次走1步,也就是走了N步,也就是X,所以X == N
并且N最大 是C-1 那么slow在相遇前的X也是C-1,所以X最多走C-1 X范围 0<=X<C 等于0是因为可能刚入环就相遇了
fast走过的距离是: L+NC+X
根据过程看出来的 fast走过的路程,至少也要走一圈在环里面,即使环很大很大,也要走一圈
我是根据这个过程,肉眼看跑出来的。
如果圆很小那么fast会走很多圈
当fast和slow相遇时
slow走过的距离是: L + X
fast走过的距离是: L+NC+X
那么有了这两个式子,和fast和slow的二倍关系,可以写出
代码:
//结论:一个指针从头结点开始,另一个从相遇点开始,同时走,每次走1步,他们会在入口点相遇
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode* slow,*fast;
slow = fast = head;
while(fast && fast->next)//奇数偶数情况结束,fast或者fast->next就会为空
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//相遇
struct ListNode* cur,*meetnode;
cur = head;
meetnode = slow;
while(meetnode != cur)//他们肯定会相遇,因为L=N*C-X N>=1
{
cur = cur->next;
meetnode = meetnode->next;
}
return meetnode;
}
}
return NULL;
}
求链表中环的长度
//
求环的长度,在相遇点在用一个指针遍历一遍直到相等