剑指 Offer 03. 数组中重复的数字(不修改原数组)

 https://www.acwing.com/problem/content/description/15/

显然此题可以用桶法做,空间换时间

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int a[1005]={0};
        int n=nums.size();
        for(int i=0;i<n;i++)a[nums[i]]++;
        for(int i=0;i<n;i++)
            if(a[nums[i]]>=2)
                return nums[i];
        return 0;
    }
};

但是题目要求可以用o(1)的空间,这里可以用抽屉原理的性质二分划分二段性
即从中间划分两个不同区间,其中的数个数 由于有个重复的数在其中一个区间中,可以得出两个区间数的个数不同
由这种性质来二分,求出区间的数的个数的,较大值的区间为答案所在范围,不断二分选取即可,直到区间为1即得出答案
要注意的是,这里的二分区间,[l,mid]与[mid+1,r]均为值,而不是nums下标

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int l = 1, r = nums.size() - 1;
        while (l < r) {
            int mid = l + r >> 1;
            int s = 0;
            for (auto x : nums) s += x >= l && x <= mid;//遍历nums寻找左区间[l,mid]数的个数
            if (s > mid - l + 1) r = mid;//左区间数的个数大于l~mid,即mid-l+1,即左区间为答案区间,右边界缩小
            else l = mid + 1;//左边界增大
        }
        return r;
    }
};

 

posted @   风乐  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示