找出數組中重複的數字。ios
在一個長度爲n的數組裏的全部數字都在0~n-1的範圍內,數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每一個數字重複了幾回。請找出數組中任意一個重複的數字。例如,若是輸入長度爲7的數組{2,3,1,0,2,5,3},那麼對應的輸出是重複的數字2或者3。(不要求輸出全部的重複數字,找到其中之一便可)c++
對輸入的數組先進行排序,而後從頭到位遍歷排序好的數組,當出現第一個數組下標與存儲的值不同的(array[i] != i),就說明找到了重複數字。排序須要的時間複雜度爲O(nlgn)。見示例代碼中的findRepeatNumberWithSort。數組
使用一個輔助的數組,長度爲n,如:tmp[n],而後開始遍歷原始數組spa
1.若是數組中出現數字x,就判斷數組下標爲x的節點是否仍是初始值0,即tmp[x]是否爲0;code
2.若是tmp[x] == 0,就標記爲1,而後繼續遍原始數組的下一個元素,繼續步驟1;blog
3.若是tmp[x] != 0,說明以前已經表標記爲1了,即以前已經出現過這個相同的元素,即已經找到重複數字了。排序
這種方法因爲須要使用一個長度爲n的輔助數組,空間複雜度爲O(n)。見示例代碼中的findRepeatNumberWithExArray。it
不使用輔助數組,也不用提早排序的方法,暫且稱爲動態排序法吧。io
先考慮另一種狀況:class
假如一個排序好的長度爲n的數組,數組中的數字爲0~n-1,而且沒有重複數字,那這個數組中存儲的數字應該是:array[0]=0,array[1]=1,array[2]=2....array[n-1]=n-1。也就是說數組的下標應該是跟存儲的值是同樣的。
回到這個需求:
若是數組中的數字有重複,說明確定存在array[i]=i而且array[j]=i(可能還有array[k]=i,array[l]=i.....)。
大前提了解了,下面開始按照這個思路查找重複數字。
從原始數組第0個位置開始遍歷,
1.假如 array[i] == i 說明,這個位置放置了對的數值,而後開始查檢查array[i+1];
2.假如 array[i] != i ,假如值爲x,判斷array[x]是否是等於x,若是是說明array[i]和array[x]都等於x,查找到了2個x,說明任務結束,能夠返回結果了;
3.假如 array[i] != i ,假如值爲x,判斷array[x]是否是等於x,若是不是,就把array[i]跟array[x]的數字交換,使得array[x]=x,這樣x就放到了array[x]的位置上,也就是找到對應的位置了,而後繼續步驟1,判斷當前的array[i]的數字。
經過這種思路,能夠看到不須要提早對數組進行排序,只須要在判斷的時候順便排序便可,只需一個循環,時間複雜度是O(n),因爲只須要使用一個輔助的空間用於交換數據,空間複雜度是O(1)【ps:甚至能夠不用輔助空間來交換兩個數字】。
見示例代碼中的findRepeatNumberDynamicSort。
1 #include <iostream> 2 #include <algorithm> 3 4 using namespace std; 5 const int ARR_LENGTH = 7; 6 7 /************************************************************************/ 8 /* @brief 使用sort查找數組中其中一個重複數字 9 /* @param arr數組 10 /* @param length數組長度 11 /* @return 數組中其中一個重複的數字,-1表示沒找到 12 /************************************************************************/ 13 int findRepeatNumberWithSort(int* arr, const int length) 14 { 15 int result = -1; 16 17 //入參有問題直接返回,少於2個數字確定沒有重複的 18 if (!arr || length < 2) 19 { 20 return result; 21 } 22 23 sort(arr, arr + length); 24 for (int i = 0; i < length; ++i) 25 { 26 if (arr[i] != i) 27 { 28 result = arr[i]; 29 break; 30 } 31 } 32 return result; 33 } 34 35 /************************************************************************/ 36 /* @brief 使用額外的輔助數組查找數組中其中一個重複數字 37 /* @param arr數組 38 /* @param length數組長度 39 /* @return 數組中其中一個重複的數字,-1表示沒找到 40 /************************************************************************/ 41 int findRepeatNumberWithExArray(int* arr, const int length) 42 { 43 int result = -1; 44 45 //入參有問題直接返回,少於2個數字確定沒有重複的 46 if (!arr || length < 2) 47 { 48 return result; 49 } 50 51 //一個臨時的輔助數組 52 int *tmpArr = new int[length]; 53 memset(tmpArr, 0, sizeof(int)*length); 54 55 for (int i = 0; i < length; ++i) 56 { 57 if (tmpArr[arr[i]] != 0) 58 { 59 result = arr[i]; 60 break; 61 } 62 else 63 { 64 tmpArr[arr[i]] = 1; 65 } 66 } 67 delete[] tmpArr; 68 tmpArr = nullptr; 69 return result; 70 } 71 72 /************************************************************************/ 73 /* @brief 不使用輔助數組,動態排序法查找重複數字 74 /* @param arr數組 75 /* @param length數組長度 76 /* @return 數組中其中一個重複的數字,-1表示沒找到 77 /************************************************************************/ 78 int findRepeatNumberDynamicSort(int* arr, const int length) 79 { 80 int result = -1; 81 82 //入參有問題直接返回,少於2個數字確定沒有重複的 83 if (!arr || length < 2) 84 { 85 return result; 86 } 87 88 int i = 0; 89 while (i < length) 90 { 91 int key = arr[i]; 92 //若是數組下標和存儲的值相同(arr[i]等於i),說明這個值已經放到了它應該在的地方(即已經排序到了正確的位置),繼續數組中的下一個值 93 if (key == i) 94 { 95 ++i; 96 } 97 else 98 { 99 //因爲key跟i不相同,而且arr[key],arr[i]這兩個位置都存儲了同一個值key,說明找到了相同的數字,結束循環,返回結果 100 if (arr[key] == key) 101 { 102 result = key; 103 break; 104 } 105 //讓arr[i]和arr[key]的值交換,使得arr[key]這個位置存放他該放的值,即arr[key]等於key 106 else 107 { 108 arr[i] = arr[key]; 109 arr[key] = key; 110 } 111 } 112 } 113 return result; 114 } 115 116 int main() 117 { 118 int arr[ARR_LENGTH] = { 2,3,1,0,2,5,3 }; 119 cout << "原始數據:" << endl; 120 121 for (int i = 0; i < sizeof(arr) / sizeof(int); ++i) 122 { 123 cout << arr[i] << " "; 124 } 125 126 int repeat = findRepeatNumberWithSort(arr, ARR_LENGTH); 127 cout << "\n\n排序法查找重複數字:" << repeat << endl; 128 129 repeat = findRepeatNumberWithExArray(arr, ARR_LENGTH); 130 cout << "\n輔助數組法查找重複數字:" << repeat << endl; 131 132 repeat = findRepeatNumberDynamicSort(arr, ARR_LENGTH); 133 cout << "\n動態排序法查找重複數字:" << repeat << endl; 134 135 return 0; 136 }