查找數組中重複的數字(一)

需求

  找出數組中重複的數字。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。

 

c++示例代碼以下:

  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 }

 

運行結果:

相關文章
相關標籤/搜索