1. 程式人生 > >【C語言】一個數組中只有兩個數字是出現一次,其他所有數字都出現了兩次。 找出這兩個數字,程式設計實現。

【C語言】一個數組中只有兩個數字是出現一次,其他所有數字都出現了兩次。 找出這兩個數字,程式設計實現。

一看到這道題,我想到了之前學習過的異或。我們知道兩個相同的數字異或的結果是 0,因為在計算機中,異或運算是按照二進位制位來運算的,相同為 0 ,相異為  1任何數與 0 異或都等於它自己。既然我們要找出來一組數中不同的兩個數字,也可以採用這種方法。

但是這次不是直接異或,而是要分組。將陣列的資料分成兩組,把這兩個不一樣的數分到兩個組裡,這樣最後的異或結果就是這兩個數了。那麼具體怎麼做呢?

第一步  所有數字異或

我們先將所有的數字異或一遍,結果儲存在num中。

第二步  找num的二進位制位中的1的位置

因為根據異或法則,相同為 0 ,相異為 1,那麼如果兩個數異或的結果num中二進位制位中有1,就說明這兩個數字不一樣。這樣問題就變成找num二進位制位中的1,遍歷32次就可以檢查所有位。一旦找到一個位是1,我們便出迴圈不再查詢,因為已經可以證明這兩個數不一樣了。接著我們可以將這個結果儲存在pos中,以便分組。

第三步  按照pos位為0或者1分組

根據第二步,找到1就跳出來儲存為pos,那麼我們再來一個迴圈,判斷所有數字異或後的結果,如果是1,分為一個組,否則,進入另一個組。

這樣做,直到最後,所有的數字異或結束,相同的為 0,不同的則是這個數。具體程式碼如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include<stdlib.h>

void find_diff_num(int *arr, int sz,int* px,int* py)
{
//1.所有數字異或
	int num = 0;
	int i = 0;
	int pos = 0;
	for (i = 0; i < sz; i++)
	{
		num ^= arr[i];
	}

//2.找num的二進位制位中的1的位置
	for (i = 0; i < 32; i++)
	{
		if (((num >> i) & 1) == 1)
		{
			pos = i;
			break;
		}
	}
//3.按照pos位為0或者1分組
	for (i = 0; i < sz; i++)
	{
		if (((arr[i] >> pos) & 1) == 1)
		{
			*px ^= arr[i];
		}
		else
		{
			*py ^= arr[i];
		}
	}
}


int main()
{
	int arr[] = { 1, 2, 3, 4, 5, 1, 2, 3, 4, 6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int n1 = 0;
	int n2 = 0;
	find_diff_num(arr,sz,&n1,&n2);
	printf("%d %d", n1, n2);
	system("pause");
	return 0;
}