【C語言】一個數組中只有兩個數字是出現一次,其他所有數字都出現了兩次。 找出這兩個數字,程式設計實現。
阿新 • • 發佈:2019-01-01
一看到這道題,我想到了之前學習過的異或。我們知道兩個相同的數字異或的結果是 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; }