原創博文,轉載請注明出處!
# 題目
在一個長度為n+1的數組里的所有數字都在1~n的范圍內,所以數組中至少有一個數字是重復的。請找出數組中任意一個重復的數字,但不能修改輸入的數組。例如,如果輸入長度為8的數組{2,3,5,4,3,2,6,7},那么對應的輸出是重復的數字2或者3。
# 思路
借鑒二分查找的思想,將數字1~n拆分成1~m和m+1~n兩部分,如果數字范圍1~m中數字個數大於m,則重復數字在1~m中間,否則重復數字一定在數字范圍m+1~n中。基於二分查找法不能找到全部的重復數字,例如{2,2,3,3,4,5,6,7}中數字區間為1~2的范圍內2出現兩次,但1沒有出現,不能確定是每個數字出現一個還是某個數字出現兩次。
# 代碼

1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 class Solution{ 5 public: 6 int duplication(vector<int> vec) 7 { 8 // 空數組 9 int length = vec.size(); 10 if(vec.size() == 0) 11 return -1; 12 13 // 數字超界 14 for(int i =0;i<length;++i) 15 { 16 if(vec[i]<1 || vec[i]>length-1) 17 return -1; 18 } 19 // 定義數字范圍 20 int begin = 1; 21 int end = length-1; 22 23 // 指定數字范圍內的數字個數 24 while(begin<=end) 25 { 26 // 計算數字范圍的中點 27 int mid = (begin + end)>>1; 28 29 // 統計指定數字范圍內的數字個數 30 int count = countrange(vec,begin,mid,length); 31 32 if(end > begin) 33 { 34 // 更新數字范圍 35 if(count>(mid - begin + 1)) 36 end = mid; 37 else 38 begin = mid + 1; 39 } 40 else 41 { 42 if(count > 1) 43 return begin; 44 else 45 break; 46 } 47 } 48 49 return -1; 50 } 51 52 int countrange(vector<int> vec,int begin,int end,int length) 53 { 54 int count=0; 55 for(int i=0;i<length;++i) 56 { 57 if(vec[i]>=begin && vec[i]<=end) 58 ++count; 59 } 60 61 return count; 62 } 63 }; 64 65 int main() 66 { 67 vector<int> vec ; 68 vector<int> vec1 = {1,2,3,4,5,6,7}; 69 vector<int> vec2 = {1,1,2,3,4,5,6}; 70 vector<int> vec3 = {2,2,3,3,4,5,6}; 71 72 73 Solution solution; 74 cout<<solution.duplication(vec)<<endl; 75 cout<<solution.duplication(vec1)<<endl; 76 cout<<solution.duplication(vec2)<<endl; 77 cout<<solution.duplication(vec3)<<endl; 78 79 return 0; 80 }
# 復雜度
時間復雜度為O(nlogn),空間復雜度為O(1)
# 測試用例
- 空數組
- 數字超界
- 數組中包含一個重復數字
- 數組中包含多個重復數字