目录
如果链表存在环,那么两个以不同速度移动的指针必定会在某个时刻指向同一个节点。
一、题目链接
二、题目简述
三、采用弗洛伊德龟兔赛跑算法
如果链表存在环,那么两个以不同速度移动的指针必定会在某个时刻指向同一个节点。
定义两个指针:兔子和乌龟,分别指向头节点
- 乌龟一次走一步,兔子一次走两步
- 当兔子走向终点时(null或者next是null),则链表不存在环.
- 兔子和乌龟能够在某一时刻指向同一节点,可以判断链表存在环.
四、代码实现
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//龟兔赛跑弗洛伊德算法
ListNode rabbit = head;//兔子 快 2
ListNode turtle = head;//乌龟 慢 1
//兔子一次两步,乌龟一次一步,如果兔子走到终点,则不是环形
//如果兔子走到跟与乌龟重合,则是环形
while(rabbit != null && rabbit.next != null){
turtle = turtle.next;
rabbit = rabbit.next.next;
if(turtle == rabbit){//能相遇
return true;
}
}
return false;//不能相遇
}
}
五、拓展(力扣142 -- 判断环形链表并找到环入口)
(1)题目跳转:力扣142
(2)解决思路:采用上述的弗洛伊德龟兔赛跑算法
- 当它们第一次相遇时,乌龟回到首节点,兔子保持原位
- 之后,兔子和乌龟一次只能走一步
- 当它们第二次相遇时即为环入口.
(3)代码实现
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
//弗洛伊德龟兔赛跑算法
ListNode rabbit = head;//兔
ListNode turtle = head;//龟
boolean flag = false;
while(rabbit != null && rabbit.next != null){
turtle = turtle.next;
rabbit = rabbit.next.next;
if(turtle == rabbit){//第一次相遇,证明肯定有环且有入口
turtle = head;//乌龟指向头节点
while(true){
if(turtle == rabbit){//第二次相遇
return turtle;
}
turtle = turtle.next;
rabbit = rabbit.next;
}
}
}
return null;//第一次没相遇证明无环
}
}