目录
1.概念以及用途
Floyd判圈算法,又被称之为龟兔赛跑算法(为什么叫龟兔赛跑呢?是因为这个算法里面用到了一个快指针和一个慢指针,就犹如那个乌龟和兔子一样,因此也被称之为龟兔赛跑算法),常用于解决以下问题
- 判断链表是否有环
- 计算环的长度
- 寻找环的起点
2.具体解决代码以及逻辑推理
(1)判断链表是否有环
我们可以设置一个快指针和一个慢指针,快指针每次走两个位置,慢指针每次走一个位置,然后分情况
- 如果没有环,那么快指针先到null
- 如果有环,那么fast==slow
- 当然还有一个细节,就是两个指针的位置不同,若起始指针为head,那么,slow=head,fast=head.next;
bool ifrool(Node head)
{
if (head == null)
{
return false;
}
Node slow = head;
Node fast = head.next;
while (slow != fast && fast != null && fast.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
return slow == fast;
}
(2)判断环的长度
当快慢指针相遇时,就已经说明了,这个是存在环的,然后就可以用另外一个flag指针让其一步一步移动,直到再次移动到这个相遇点,这个就可以求出环的长度
int length(Node head)
{
if (head == null)
{
return 0;
}
Node slow = head;
Node fast = head.next;
while (slow != fast && fast != null && fast.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
if (slow == fast)
{
int num = 1;
Node temp = slow.next;
while (temp != slow)
{
temp = temp.next;
num++;
}
return num;
}
return 0;
}
(3)判断环的起始点
这个涉及到逻辑的推理了
我们首先假设,起点进入环的长度为a,环的长度为b,慢指针的速度为1,快指针的速度为2
然后我们就可以分析出,如果慢指针走了s的话,那么快指针则走了2s,那么我们就可以推出s=nb
然后我们将其中一个指针放在起点,这两个指针以相同速度走,那么一定会在起点首次相遇 (这个是结论)
3.例题
#include<bits/stdc++.h>
using namespace std;
int n;
int a[105];
int fast, slow;
int main()
{
cin >> n;
for (int i = 0; i <= n; i++)
cin >> a[i];
fast = a[0];
slow = a[0];
do
{
fast = a[a[fast]];
slow = a[slow];
} while (fast != slow);
fast = a[0];
while (fast != slow)
{
fast = a[fast];
slow = a[slow];
}
cout << fast << endl;
return 0;
}