目录
1.概念以及用途
2.具体解决代码以及逻辑推理
(1)判断链表是否有环
(2)判断环的长度
(3)判断环的起始点
3.例题
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.例题
LeetCode287寻找重复数
#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;
}