leetcode_middle_29_287. Find the Duplicate Number

题意:

 有一个大小是n+1的数组。数组的元素都是[1, n]区间内的数字。必有且仅有一个数字重复(可能重复不止一次),找出这个数字

分析:

这个题的数字很有特色,数字都小于最大角标,就给了利用角标的机会。但怎么利用呢,画画想想之后突然想到是不是可以利用值做角标再用得到的值再做角标,这样必定有一个循环。因为这个循环,想到使用双指针,但是之后存在什么规律就没什么规律了。所以只好考虑另一种方法,(抽屉原理)因为本来是1 2 3 4 5 6 7...每个一个,但是这个题目的核心之处在于,比如2有两个(核心特征一般化),则必然可以推出这个数组不均匀了(左半比右半多了一个),所以可以确定这个数在多的那一边,所以二分查找:

public class Solution {
    public int findDuplicate(int[] nums) {
        int low = 1;
        int high = nums.length -1;
        int mid = 0;
        while(low<high) {
            mid = low + (high-low)/2;
            int c = com(nums, mid);
            if(c > mid) {                //比如小于等于4的数有5个,那就应该查1到4
                high = mid;
            }else{                       //比如小于等于4的数的个数是4个或者更少,应该查5到7
                low = mid+1;
            }
        }
        return low;
    }
    private int com(int[] nums, int mid) {
        int count = 0;
        for(int i=0; i < nums.length; i++){
            if(nums[i] <= mid)
                count++;
        }
        return count;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值