題目:
在一個長度為n的數組里的所有數字都在0到n-1的范圍內。 數組中某些數字是重復的,但不知道有幾個數字是重復的。也不知道每個數字重復幾次。請找出數組中任意一個重復的數字。
例如,如果輸入長度為7的數組{2,3,1,0,2,5,3},那么對應的輸出是重復的數字2或者3。
思路:
1、排序
將數組排序,然后掃描排序后的數組即可。
時間復雜度:O(nlogn),空間復雜度:O(1)
2、哈希表
從頭到尾掃描數組,每掃描到一個數字,判斷該數字是否在哈希表中,如果該哈希表還沒有這個數字,那么加入哈希表,如果已經存在,則返回該數字;
時間復雜度:O(n),空間復雜度:O(n)
3、交換
0~n-1正常的排序應該是A[i]=i;因此可以通過交換的方式,將它們都各自放回屬於自己的位置;
從頭到尾掃描數組A,當掃描到下標為i的數字m時,首先比較這個數字m是不是等於i,
如果是,則繼續掃描下一個數字;
如果不是,則判斷它和A[m]是否相等,如果是,則找到了第一個重復的數字(在下標為i和m的位置都出現了m);如果不是,則把A[i]和A[m]交換,即把m放回屬於它的位置;
重復上述過程,直至找到一個重復的數字;
時間復雜度:O(n),空間復雜度:O(1)
(將每個數字放到屬於自己的位置最多交換兩次)
代碼:
交換
#include <iostream> using namespace std; bool duplicate(int numbers[],int length,int* duplication){ if(numbers==NULL || length<=1){ duplication=NULL; return false; } for(int i=0;i<length;i++){ while(numbers[i]!=i){ if(numbers[i]==numbers[numbers[i]]){ *duplication=numbers[i]; return true; } int tmp=numbers[i]; numbers[i]=numbers[tmp]; numbers[tmp]=tmp; } } return false; } int main() { int A[]={2,3,1,0,2,5,3}; int len=sizeof(A)/sizeof(A[0]); int duplication; cout << duplicate(A,len,&duplication) << endl; cout << duplication << endl; return 0; }
在線測試OJ:
http://www.nowcoder.com/books/coding-interviews/623a5ac0ea5b4e5f95552655361ae0a8?rp=2
AC代碼:
class Solution { public: // Parameters: // numbers: an array of integers // length: the length of array numbers // duplication: (Output) the duplicated number in the array number // Return value: true if the input is valid, and there are some duplications in the array number // otherwise false bool duplicate(int numbers[], int length, int* duplication) { if(numbers==NULL || length<=1){ duplication=NULL; return false; } for(int i=0;i<length;i++){ while(numbers[i]!=i){ if(numbers[i]==numbers[numbers[i]]){ *duplication=numbers[i]; return true; } int tmp=numbers[i]; numbers[i]=numbers[tmp]; numbers[tmp]=tmp; } } return false; } };