一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
找出这两个数字,编程实现。
想要完成该题目的要求首先要有明确的思路:
1、用异或实现。因为异或简单快捷。
2、先将所有的数组元素逐个异或,所得到的结果为两个只出现一次的数字异或之后的结果并存入result中(出现两次的数字异或之后结果均为0)。
3、再通过标志位flag的左移操作将result中的一个1的位置找出,因为两数相异或的结果为1所在的位,在该位两数的二进制必然不同。
4、最后再通过flag循环遍历数组将数组分成两组,即通过flag为1的那个二进制位将数组里只出现一次的两个数字分开。(相同的数字必然出现在同一组)
具体实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>
void foundnums(int* num,int len)
{
assert(num);
int date1 = 0, date2 = 0;
int i = 0;
int result = num[0];
int flag = 1; //标志位,用于找出异或之后result里面的一个1
for (i = 1; i < len; i++)
{
result ^= num[i]; //所有元素逐个异或之后的值(也就是两个不同元素异或的值肯定非0)
}
while (result)
{
if ((result & flag) == 1)
{
break; //找到result里面的一个1,因为两数异或之后1所在的位数必然可以表示两数在该位不同
}
flag <<= 1;
}
for (i = 0; i < len; i++) //将num中的所有数字分两组 即通过if和else将date1和date2分开
{
if (num[i] & flag) //分开的原理:相同的数字在flag为1那位必然相同 即分在同一组
{
date1 ^= num[i];
}
else
{
date2 ^= num[i];
}
}
printf("%d %d",date1,date2 );
}
int main()
{
int num[] = { 1,2,3,4,5,6,1,2,5,6 };
int len = sizeof(num)/sizeof(num[0]);
foundnums(num,len);
return 0;
}
结果: