larscheng / algo

0 stars 0 forks source link

【Check 87】2024-05-31 - 287. 寻找重复数 #195

Open larscheng opened 1 month ago

larscheng commented 1 month ago

287. 寻找重复数

larscheng commented 1 month ago

思路

n+1个数字放在数组中,n+1个数字的范围都在【1,n】中,所以必定至少有一个重复数字 通过2分法来找这个重复数字,需要一个2分条件,并且应该对值域进行2分,而不是下标索引2分

值域2分,mid = (1+n)/2 在原数组中小于等于mid的数字个数为count

代码

    public int findDuplicate(int[] nums) {
        int left = 1;
        //给n+1个数字的数字,其值域在1-n,所以n=len-1
        int right = nums.length - 1;
        while (left<right){
            int mid = (left+right)/2;
            int count =0;
            //数组中小于等于mid的元素个数
            for (int num : nums) {
                if (num<=mid){
                    count++;
                }
            }
            //一个萝卜一个坑,萝卜多了,肯定是挤在了一个坑(有重复)
            if (count > mid) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }

复杂度

larscheng commented 1 month ago

思路

O(n)/O(1)

代码

   public int findDuplicate(int[] nums) {
        int slow = 0;
        int fast = 0;
        //慢指针每次1步,快指针每次2步
        slow = nums[slow];
        fast = nums[nums[fast]];
        while (slow!=fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        fast = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        return fast;
    }