287. 不修改数组找出重复的数字

不修改数组找出重复的数字

解题思想

题目要求不能修改输入的数组,我们可创建一个长度为n+1的辅助数组,逐一复制,我们就很容易发现哪个数字重复了。
由于需要创建一个数组,该方案需要O(N)的辅助空间。

接下来我们尝试避免使用O(n)的辅助空间。为什么数组中会出现重复数字。因为限定了范围的缘故。
好比有九个抽屉,要放十个苹果,那么必定有一个抽屉包含两个苹果。我们以限定范围有着手点,利用二分思想进行查重。

我们把1n的数字从中间数字m分为两部分。1m,m+1n。在数组nums中分别统计数字范围1m出现的次数。如果次数大于m那么重复的数字肯定在1~m之间。
利用这个限定范围的思想继续二分查找。最后终究会发现某个数字出现了两次。那么查重成功。

上述代码按照二分查找的思路。如果输入长度为n的数组,那么函数countRange奖杯调用logn次,每次需要O(n)的时间,因此总的时间复杂度是O(nlogn)。
空间复杂度为O(1)。这种算法相当于用时间换取空间。

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int start,end,mid;
        start = 1;
        end = nums.size()-1;
        while(start<=end){
            mid = (start+end)/2;
            int count = countRange(nums,start,mid);
            if(end == start){
                if(count > 1){
                    return start;
                }
            }
            if(count > (mid - start + 1)){  //寻找嫌疑
                end = mid;
            }else{
                start = mid+1;
            }

        }
        return 0;

    }

    int countRange(vector<int>& nums,int start,int end){
        int count = 0;
        for(int i=0;i<nums.size();i++){
            if(nums[i]>=start&&nums[i]<=end){
                ++count;
            }
        }
        return count;
    }
};
posted @ 2021-03-01 16:07  focusDing  阅读(102)  评论(0编辑  收藏  举报