題目:
在一個長度為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;
}
};
