在一個數組中查找兩個重復出現的數字


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM