判断链表有无环并且找到环的入口

题目

解法


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;

    }
}


posted @ 2021-10-01 23:03  刚刚好。  阅读(53)  评论(0编辑  收藏  举报