1. 程式人生 > >LeetCode 287.尋找重複數 Find the Duplicate Number

LeetCode 287.尋找重複數 Find the Duplicate Number

題目連結

一個長度是n+1的陣列,出現的整數都在1到n之間(包括1和n),已知有一個重複出現的整數。求該整數。

要求:

1.不能更改原陣列

2.空間複雜度O(1)

3.時間複雜度小於O(n²)

4.陣列中只有一個重複的數字,但它可能不止重複出現1次。


花了點時間才想明白,原來二分法可以這麼使用。


當n為奇數,且重複出現的數字為奇數,奇數個數>偶數個數

當n為奇數,且重複出現的數字為偶數,偶數個數>=奇數個數


當n為偶數,且重複出現的數字為奇數,奇數個數>偶數個數

當n為偶數,且重複出現的數字為偶數,偶數個數>奇數個數


總結一下就是:

當奇數個數>偶數個數時,重複出現的數字在奇數裡,那麼繼續從奇數的奇數和奇數的偶數裡找。

當偶數個數>=奇數個數時,重複出現的數字在偶數裡,那麼繼續從偶數的奇數和偶數的偶數裡找。


什麼時候算是找到了呢,

當奇數個數==0,說明偶數裡全是重複的數字(對嗎,欸,是嗎)

當偶數個數==0,說明奇數裡全是重複的數字


程式碼如下:

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int len=nums.size();
        int s1=1,s2=2,d=2,couts1,couts2;//糟糕的命名,s1表示奇,s2表示偶,
        int s_1,s_2;
        while(1)
        {
            couts1=0;
            couts2=0;
            s_1=s1%d;
            s_2=s2%d;
            for(int i=0;i<len;i++)
            {
                if(nums[i]%d==s_1) couts1++;
                if(nums[i]%d==s_2)  couts2++;
            }
            
            if(couts1==0)
            {
                for(int i=0;i<len;i++)
                {
                    if(nums[i]%d==s_2)  return nums[i];
                }
            }
            if(couts2==0)
            {
                for(int i=0;i<len;i++)
                {
                    if(nums[i]%d==s_1)  return nums[i];
                }
            }
            
            if(couts1>couts2)
            {
                s1=s1;
                s2=s1+d;
            }
            else
            {
                s1=s2;
                s2=s2+d;
            }
            d*=2;
        }
    }
};