Find the Duplicate Number--重复数字问题

问题描述

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+1个整数组成的数组,每个整数范围在1到n之间(保证至少有一个数重复),假设只有一个重复数字,但可以重复多次
算法要求:
数组只读、空间复杂度常数阶、时间复杂度小于平方阶

思路:
假设数组长度为nlen,可以设定下界low=1,上界high=nlen,中间值mid=(low+high)/2,从理论上讲,如果数字没有重复,mid值和实际算出来数组的中值应该是一样的(最大值不大于数组长度,也就是没有条数字)。但由于问题中最大值不会大于数组长度,保证了 一定会有一个重复数字,利用mid可以把数组分成两部分,一部分的值小于等于mid,另一部分的值大于mid,计算出第一部分的个数count,如果第一部分的个数大于mid,可以知道重复的数字是在这一部分里,否则在另一部分里。该部分可以得到新的low值和high值,比如在第一部分,low不变,high=mid,这两个值是为了得到新的mid值服务的,(low和high只是数的序号,不是真正的数组值)然后可以更新low和high的值,以此类推。


下面举两个例子:
(1)数组{1,4,2,4,2}

循环条件:low < high
初始: low=1,high=5,mid=3,count=3

第一次:判断count mid
low=1,high=mid=3,mid=2,count=3

第二次: 判断count mid
low=1,high=mid=2,mid=1,count=1

第三次: 判断:count < mid
low=mid+1=2,high=2
循环结束

(2)数组{1,4,4,2,4}

循环条件:low < high
初始: low=1,high=5,mid=3,count=2

第一次:判断count < mid
low=mid+1=4,high=5,mid=4,count=3

第二次: 判断count mid
low=4,high=mid=4
循环结束


上述设计思路满足算法要求,时间复杂度o( nlog2n
注:
(1)low更新是为mid+1,否则会死循环(第一个例子)
(2)count的计算值是小于等于mid的数的个数,不是low和mid之间数值的个数。


c++程序如下:

class Solution {
public:
int findDuplicate(vector<int>& nums){
    int n = nums.size();
        int low = 1;
        int high = n;
        int mid;
        while(low<high)
        {
             mid = (low + high) / 2;
            if (count(low,high,nums)<=mid)
                low=mid+1;
            else
                high= mid;
        }
        return low;

    }
    int count(int low, int high, vector<int>& nums)
    {
        int count0 = 0;
        int n = nums.size();
        int mid = (low + high) / 2;
        for (int i = 0;i <n;i++)
        {
            if (nums[i] <=mid )
                count0++;

        }
        return count0;
    }
};

关联问题:二分查找

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值