LintCode刷题随笔

 

633. 寻找重复的数关注问题

描述

给出一个数组 nums 包含 n + 1 个整数,每个整数是从 1 到 n (包括边界),保证至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

1.不能修改数组(假设数组只能读)
2.只能用额外的O(1)的空间
3.时间复杂度小于O(n^2)
4.数组中只有一个重复的数,但可能重复超过一次

您在真实的面试中是否遇到过这个题?  是

题目纠错

样例

样例 1:

输入:
[5,5,4,3,2,1]
输出:
5

样例 2:

输入:
[5,4,4,3,2,1]
输出:
4

思路:限制实在太多了有木有,考虑到空间约束,貌似我们只能一个数一个数地试,但是又要求小于O(n^2)的复杂度,甚至都逼得孩子想到了随机大法(雾)。等等,一个个试?一个个试实在太慢了,有没有办法?自然可以联想到二分答案的做法,那么这题可以二分答案吗,我们试试。

假设我们当前在试x是否是重复的数,由于一共有n+1个数,而每个数都是处于[1,n]的,那么重复的数必定至少出现了两次,假设重复的数为y,并且满足y<=x,那么处于[x+1,n]的数最多只会出现一次,即>x的数的个数一定满足<=n-x,而一共有n+1个数,也就是说,设一共有z个数满足<=x,那么z>=(n+1)-(n-x)=x+1。

换言之,如果<=x的数的个数>=x+1,则重复的数一定处在[1,x]之中,否则处在[x+1,n]。

class Solution {
public:
    /**
     * @param nums: an array containing n + 1 integers which is between 1 and n
     * @return: the duplicate one
     */
    //二分法 因为总共有n+1个数 且只有一个数重复  所以如果后面无重复 最多只有 n-mid个数  那么前面会剩下 mid+1 个数 必有重复
    int check(vector<int> &nums,int n,int num){// 统计小于等于num的个数
        int i,c=0;
        for(i=0;i<n;++i){
            if(nums[i]<=num)++c;
        }
        return c;
    }
     
    int findDuplicate(vector<int> &nums) {
        // write your code here
        int i,n=nums.size(),Mid,L=1,R=n-1;
        while(L<R){
            Mid=(L+R)>>1;
            if(check(nums,n,Mid)<=Mid){
                L=Mid+1;
            }
            else R=Mid;
        }
        return R;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值