母胎solo20年总结出的单身狗问题

一 思想精髓

单身狗问题的关键就是或用^的性质:

亦或操作:二进制位置相同取0,相异取1

①0^a=a;

②a^a=0;

③a^1 那么a的所有位置按位取反

那么->一个数字被另外一个数字亦或两次等于它本身(相当于没有^,^运算满足交换律)

二 问题描述

①一条单身狗 :

一个数组中只有1个数字是出现一次,其它所有数字都出现了两次
编写一个函数找出这两个只出现一次的数字

刚开始定义的临时变量是0的原因: 0^任何数字都是它本身-》方便找出单身狗

将所有的数字进行^操作,那么最后就可以找出单身狗。

举例:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
int main()
{
	int arr[] = { 1,1,3,3,5,5,8 };
	int i = 0;
	int len = sizeof(arr) / sizeof(arr[0]);
	int ret = 0;
	for (i = 0; i < len; i++)
	{
		ret = ret ^ arr[i];
	}
	printf("单身狗是%d", ret);
	return 0;
}

②两条单身狗

一个数组中有2个数字是出现一次,其它所有数字都出现了两次
编写一个函数找出这两个只出现一次的数字

解题思路:这个问题稍微复杂一点。但是核心的思想仍然是利用好^。将两只单身狗的问题转化成一只单身狗的问题进行解决。

由于这个数组中存在两个单身狗,因此我们需要对单身狗进行分组,将不同的单身狗分在一组。其他剩下的元素两两配对。

因此可以对二进制位从低位向高位进行选择,如果是1的话,那么说明一个单身狗的这个位置是1,另一个单身狗的这个位置是0,是不同的,就可以将他们分开了。而对于相同的数字,这个位置肯定也是相同的。

1.先对原来的数组进行^,那么结果就是两个单身狗^的结果。

2.找出不同的位置进行分组。

3.分别在不同的组里找出单身狗

举例:

#define _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
int main()
{
	int arr[] = { 1,1,3,3,4,5 };
	int i = 0;
	int len = sizeof(arr) / sizeof(arr[0]);
	int n = 0;
	int ret = 0;//用来存放不同的一位
	int dog1 = 0;
	int dog2 = 0;
	
	for (i = 0; i < len; i++)
	{
		n ^= arr[i];//两只单身狗亦或的结果
	}

	for (i = 0; i < 32; i++)
	{
		if ((n >> i)%2 == 1)//注意运算符优先级的问题,%2那么只能是0或者1
		{
			ret = i;//记录出分组的1的位置,若两个位置亦或的结果是1,那么两个数不同,一个是0,一个是1,作为分组的依据
			break;
		}
	}

	for (i = 0; i < len; i++)
	{
		if ((arr[i] >> ret) % 2 == 1)//如果数组中这一位数组是1
		{
			dog1 ^= arr[i];
		}

		else
		{
			dog2 ^= arr[i];
		}
	}

	printf("单身狗是:%d和%d", dog1, dog2);
	return 0;
}

三 总结

运算符的运用特别的灵活,因此平时应该多做多看多练习,加深对运算符的理解!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值