1. 程式人生 > 實用技巧 >Acwing 14 不修改陣列找出重複的數字

Acwing 14 不修改陣列找出重複的數字

給定一個長度為 \(n+1\) 的陣列 \(nums\),陣列中所有的數均在 \(1∼n\) 的範圍內,其中 \(n≥1\)

請找出陣列中任意一個重複的數,但不能修改輸入的陣列。

樣例:給定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。

本題利用抽屜原理:n+1 個蘋果放在 n 個抽屜裡,那麼至少有一個抽屜中會放兩個蘋果。
由題目我們可知,至少有一個數會出現兩次。
然後我們採用分治的思想,將每個數的取值的區間[1,n]劃分成[1,n/2]和[n/2+1]兩個子區間,然後分別統計區間內數的個數。
注意:這裡的區間是指數的取值範圍,而不是陣列下標
劃分之後,左右兩區間中一定有一個區間,區間中數的個數大於區間長度。
最後利用二分方法,不斷縮小區間長度,當區間長度為1時,即為本題的答案。
複雜度分析:利用二分縮小區間\(O(logn)\)

,每次統計其中一個子區間中的數,需要遍歷陣列,近似於\(O(n)\)

public:
    int duplicateInArray(vector<int>& nums) {
       int l=1,r=nums.size()-1;
       while(l<r)
       {
           int s=0;
           int mid=(l+r)>>1;
           for(auto x:nums)
           if(x>=l&&x<=mid) s++;
           if(s>=mid-l+1) r=mid;
           else l=mid+1;
        }
        return r;
       }
       
};