287. Find the Duplicate Number(unsolved)

寻找重复数字
本文介绍了一种高效的算法,用于在一个包含n+1个整数的数组中查找重复的数字,每个整数位于1到n之间(包括1和n)。该算法采用二分查找策略并结合抽屉原理,确保了在不修改原始数组的前提下,使用常数级别的额外空间复杂度完成任务。运行时间复杂度低于O(n^2),适合处理只有一个重复数字的情况。

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Note:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.

解答:

实际上,我们可以根据抽屉原理简化刚才的暴力法。我们不一定要依次选择数,然后看是否有这个数的重复数,我们可以用二分法先选取n/2,按照抽屉原理,整个数组中如果小于等于n/2的数的数量大于n/2,说明1到n/2这个区间是肯定有重复数字的。比如6个抽屉,如果有7个袜子要放到抽屉里,那肯定有一个抽屉至少两个袜子。这里抽屉就是1到n/2的每一个数,而袜子就是整个数组中小于等于n/2的那些数。这样我们就能知道下次选择的数的范围,如果1到n/2区间内肯定有重复数字,则下次在1到n/2范围内找,否则在n/2到n范围内找。下次找的时候,还是找一半。

注意
我们比较的mid而不是nums[mid]
因为mid是下标,所以判断式应为cnt > mid,最后返回left
而且最后判断是cnt<=mid,而非cnt

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n=nums.size()-1;
        int left=1;
        int right=n;
        while(left<right)
        {
            int mid = (left+right)/2;
            int cnt= 0;
            for(int num:nums)
            {
                if(num<=mid) cnt++;

            }
            if(cnt<=mid) left=mid+1;
            else right=mid ;
        }
             return left;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值