// 如果[1,n]的数字都只有一个,那么我们会形成一个闭合的环。
idx 1 2 3 4
val 3 1 4 2
1->3->4->2 这样就是一个闭合的环。

如果有重复数字出现的话,如下:
idx 1 2 3 4 5
val 2 4 2 3 1
1->2->4->3->2->4   这里就有一个2->4->3->2的环, 2就是重复数字

public class Solution {
    public int findDuplicate(int[] nums) {
        int slow = nums[0];
        int fast = nums[nums[0]];
        
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        
        fast = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[fast];
        }
        
        return fast;
    }
}
如果1到mid每个数字都只出现一次,在nums里<=mid的个数应该就是mid.
个数大于mid的话,前面的数字里就会有重复。

public class Solution {
    public int findDuplicate(int[] nums) {
        int n = nums.length-1, lo = 1, hi = n;
        while(lo < hi){
            int mid = lo + (hi-lo)/2, count = 0;
            for(int n: nums)
                if(n <= mid) count++;
            if(count > mid) hi = mid;
            else low = mid+1;
        }
        return lo;
    }
}

大米中的大米
12 声望5 粉丝

你的code是面向面试编程的,收集和整理leetcode discussion里个人认为的最优且最符合我个人思维逻辑的解法。