一个单身狗
一个数组中只有一个数字是出现一次,其他所有数字都出现了两次。
编写一个程序找出这个只出现一次的数字。
方法1(异或)
- a ^ a = 0
- a ^ 0 = a
- ^满足结合律
c
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,4,2,3,5};
int i = 0;
int ret = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
ret = ret ^ arr[i];
}
printf("单身狗:%d\n", ret);
return 0;
}
方法2(暴力求解法)
c
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,4,2,3,5 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
int count = 0;
int j = 0;
for (j = 0; j < sz; j++)
{
if (arr[i] == arr[j])
{
count++;
}
}
if (1 == count)
{
printf("单身狗:%d\n", arr[i]);
break;
}
}
return 0;
}
两个单身狗
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
假设是1, 2, 3, 4, 5, 6, 4, 3, 2, 1
思路:只要是不同的数,异或后肯定有1,是1的那个二进制位不相同
所以我们可以把它们分成两组(按照5和6二进制某一位的不同)
十进制 | 二进制 |
---|---|
5 | 101 |
6 | 110 |
比如:
拿最后一位分组:
1 1 3 3 5 (最后1位是1)
2 2 4 4 6 (最后1位是0)
拿倒数第二位分组:
1 1 4 4 5 (是0)
2 2 3 3 6 (是1)
过程:
1.全部异或在一起
2.计算第几位是1
3.分组
c
#include<stdio.h>
void dog2(int arr[], int sz)
{
int ret = 0;
int i = 0;
//1.全部异或在一起
for (i = 0; i < sz; i++)
{
ret ^= arr[i];
}
//2.计算ret第几位是1,得到pos
int pos = 0;
for (i = 0; i < 32; i++)
{
if (((ret >> i) & 1) == 1)
{
pos = i;
break;
}
}
//3.分组
int s1 = 0;
int s2 = 0;
for (i = 0; i < sz; i++)
{
if (((arr[i] >> pos) & 1) == 1)
s1 ^= arr[i];
else
s2 ^= arr[i];
}
printf("单身狗1是%d\n单身狗2是%d", s1, s2);
}
int main()
{
int arr[] = { 1,2,3,4,5,6,4,3,2,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
dog2(arr, sz);
return 0;
}