C语言—位运算符练习(二)—单身狗问题
前言
上一篇博客,我们留了一个思考题—单身狗问题,下面咱们对这两道题进行讲解
一、单身狗问题(1)
1.题目
有一个数组只有一个数字出现一次,其余数字都是成对出现的,编写一个函数找出只出现一次的数字。
例如:
有数组的元素是:1 2 3 4 5 1 2 3 4
5只出现了1次,要找出数字5。
2.思路
可能第一次大家看到这道题,会想到使用一个数组count[10],分别计算出,每个元素出现的次数,最后找到只出现一次的数字,再返回出去,但是有一个弊端,count[i]中的下表,能否跟数组的下表对应上,对于这道题可能可以,但是是一个未知的数组,那么就不行了。那么可以回想起之前学的 ^(按位异或) 的规律做这道题。
规律:(1)a^a=0
(2)a^0=a
(3)支持交换律
3.参考代码
#include<stdio.h>
int find_single_dog1(int arr[], int sz)
{
int ret = 0;
int i = 0;
for (i = 0; i < sz; i++)
ret ^= arr[i];;
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
int ret = find_single_dog1(arr, sz);
printf("%d", ret);
return 0;
}
二、单身狗问题(2)
1.题目
一个数组中只有两个数字出现了一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。
例如:
有数组的元素是:1,2,3,4,5,1,2,3,4,6
2.思路
这道题就比上一道题难上一些,但是方法还是一样的,还是运用 ^按位异或 进行计算,
首先,最后要返回5和6,如果看这个数组每个元素的二进制,可以分为两类。
第一类(最后一位为1):1,1,3,3,5
第二类(最后一位为0):2,2,4,4,6
那么只要我们找到其中的一个,另外一个只需要ret^pdg(第一个单身狗)即可
3.代码的实现
#include<stdio.h>
void find_single_dog2(int arr[], int sz, int* pd1, int* pd2)
{
int ret = 0;
//ret=5^7
//00000101 -- 5
//00000111 -- 7
//00000010 -- ret=2
for (int i = 0; i < sz; i++)
ret ^= arr[i];
int pos = 0;
for (int i = 0; i <32; i++)
{
if (((ret >> i) & 1) == 1)
{
pos = i;//pos=1
break;
}
}
for (int i = 0; i < sz; i++)
{
if (((arr[i] >> pos) & 1) == 1) //计算数组中元素的第pos位为1的异或
*pd1 ^= arr[i]; //根据异或的性质得到第一个单身狗数字
}
*pd2 = ret ^ *pd1;
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,7 };
int sz = sizeof(arr) / sizeof(arr[0]);
int dog1 = 0;
int dog2 = 0;
find_single_dog2(arr, sz, &dog1, &dog2); //&dog1和&dog2是返回型参数
//因为函数只能有一个返回值,
//而我们想知道两个数字,所以我们这里传地址
printf("dog1=%d dog2=%d\n", dog1, dog2);
return 0;
}
完