C语言---位运算符练习(二)---单身狗问题

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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值