判断链表有无环并且找到环的入口
题目
解法
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null) return null;
ListNode fast=head;
ListNode slow=head;
//判断有无环
while(fast!=null&&fast.next!=null && slow!=null){
fast=fast.next.next;
slow=slow.next;
if(fast==slow) break;
}
if(fast==null||fast.next==null || slow==null){
return null;
}else{
//找到环的入口
while(fast!=head){
fast=fast.next;
head=head.next;
}
return head;
}
}
}
解析
假设从链表到环的入口节点数为a,环上节点数为b, fast指针走了2s步,slow指针走了s步,fast指针和slow指针相遇后一定满足 2s-s=n*b(fast比slow多在环上走了n圈) 也就是说s=nb,那么slow指针只需要再走a步就能到达环的入口,同时从链表头结点走a步也能到达环的入口,那么我们让head和slow同时走,相遇的地方就是环的入口
变形
我们让i处的节点和nums[i]处的节点相连,如果有重复数字一定会成环(可以自己画画),重复数字就是环的入口
class Solution {
public int findDuplicate(int[] nums) {
int fast=0;
int slow=0;
while((fast==0 && slow==0) || (fast!=slow)){
fast=nums[nums[fast]];
slow=nums[slow];
}
int head=0;
while(slow!=head){
slow=nums[slow];
head=nums[head];
}
return head;
}
}
我有一壶酒
足以慰风尘
尽倾江海里
赠饮天下人