題目如下:現有一個數組長度為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 : )