原題:
一個數組中只有兩個數字是出現一次,其他所有數字都出現了兩次。
找出這兩個只出現一次的數字,編程實現。
此題要用到在數列中找出只出現一次的一個數字的方法
參考https://blog.51cto.com/14232799/2382172
此題明顯無法一次性將兩個數都找出,所以需要將數列分爲兩部分,每一部分有一個只出現一次的數,那麼此時需要的就是分離數列的條件。
沿用找出一個數時的思想,將數列進行相互異或,但這次所得的值不是隻出現一次的那個數了,因爲只出現一次的數有兩個,所以此次計算得到的是隻出現一次的兩個數的異或值。
在得到這個值後進行分析,假如得到值是4,二進制碼是0100
參照異或的定義,0代表此位兩個數的值相同,1代表此位兩個數的值不同。
eg:
只出現一次的兩個數是2和6
2的二進制碼是
0010
6的是
0110
計算得到的值(兩個數異或)就是0100,表示第三個二進制位兩個數不同
得到了此條件,就可以將數列分爲第三個二進制位爲1和第三個二進制位爲0兩個數列
再將每個數列採用找出一個數字的方法找出數字即可。
源代碼:
#include<stdio.h>
#include<stdlib.h>
int First(int arr[], int length)//得到只出現一次的兩個數的異或
{
int i,result=0;
for (i = 0; i < length; i++)
{
result ^= arr[i];
}
return result;
}
void Second(int arr[],int i,int length,int* num1, int* num2)//將數列分爲兩個數列而且找出數字
{
int j;
for (j = 0; j < length; j++)
{
if (arr[j] >> i == 0)//分離條件
{
*num1 ^= arr[j];
}
if (arr[j] >> i == 1)//同上
{
*num2 ^= arr[j];
}
}
}
int main()
{
int i = 0,num1=0,num2=0;//i用來存儲二進制位上哪一位兩個只出現一次的的數字是不同的
int* k1=&num1,* k2=&num2;//存儲要找的兩個數
int arr[] = { 1, 4, 6, 8, 2, 8, 4, 1 };
int length = sizeof(arr) / sizeof(arr[0]);
int result = First(arr, length);
while (((result >> i) & 1)==0)//找出異或值中二進制序列不同是在哪一位
{
i++;
}
Second(arr,i,length,k1,k2);//數列分離爲兩個數列和找出數字
printf("兩個數字爲%d和%d", num1, num2);
system("pause");
return 0;
}