題目如下:現有一個數組長度為n+1,里面存放有1到n-2,順序不定,其中有兩個數字出現了兩次,現在要找出那兩個數字。 例子A={2, 3, 1, 4, 5, 2, 4},
這個數組長度為7,存放了1到5,但2和4出現了兩次,程序輸出2和4
方法1 蠻力查找 主要思想:對於數組中的第i個數,查找i+1到末尾的所有整數,一個數如果出現了兩次就可以在第一次后面找到第二次出現的數。
時間復雜度 O(n^2)
#include<stdio.h>
void find_duplicates(int* num, int start, int end){
int size = end-start+1;
int i = 0;
int j = 0;
for(i=0; i<size; i++){
for(j=i+1; j<size; j++){
if(num[i] == num[j])
printf("%d\n", num[i]);
}
}
}
void main(){
int A[]={5,2,4,3,1,3,2};
find_duplicates(A, 0, 6);
}
方法2:異或(xor)
主要思想:由於限定了是1到n之間的數,且每個數至少出現一次,可以先把數組中的所有整數異或一遍,然后把結果再和1、2、3、、、n異或一遍,
這樣就得到了那兩個重復出現的整數的異或結果 x。接下來主要是想辦法把它們兩給區分開來,對於異或結果x,它的二進制表示有0和1構成,有異或的性質可知,
二進制表示的x中那些出現0的位是兩個重復數對應位置均為1或者0的結果,而出現1的位則只有一種可能:兩個數對應位置一個是0,一個是1。借助這個特點,
我們就可以選取一個特定的位置(x的那個位置是1)把原來的數組分成兩個部分,部分I對應那個特定位置為1的數,部分II對應那個特定位置為0的數,
這樣就把問題轉化為:在每個部分查找一個重復出現的數字。
時間復雜度 O(n)
代碼:
#include<stdio.h>
void find_duplicates(int* num, int start, int end){
int size = end-start+1;
int bit_flag = 0;
int i=0;
for(i=0; i<size; i++){
bit_flag ^= num[i];
}
for(i=1; i<size-1; i++){
bit_flag ^= i;
}
int division_bit = bit_flag & ~(bit_flag-1);
int a = 0;
int b = 0;
for(i=0; i<size; i++){
if(num[i] & division_bit)
a ^= num[i];
else
b ^= num[i];
}
for(i=1; i<size-1; i++){
if(i & division_bit)
a ^= i;
else
b ^= i;
}
printf("duplicate numbers a=%d \t b=%d\n", a, b);
}
void main(){
int A[]={5,2,4,3,1,3,2};
find_duplicates(A, 0, 6);
}
方法2運行結果:

轉載請注明出處 warnon : )
