位运算之妙用:识别独特数字(寻找单身狗)

2024-03-01 13:32:06 浏览数 (1)

寻找单身狗1

从数组中 的1 2 3 4 5 1 2 3 4 中找出没有另一个相同的数与其匹配的数

这个问题的原理是利用异或运算的性质。异或运算(XOR)是一种二进制运算,其特点是相同为0,不同为1。在这个问题中,数组arr中的所有元素都出现了两次,只有一个元素只出现了一次。通过异或运算,可以将出现两次的元素抵消掉,最后剩下的就是只出现一次的元素。

具体步骤如下:

  1. 初始化一个变量n为0,用于存储异或结果。
  2. 遍历数组arr,将每个元素与n进行异或运算,并将结果赋值给n。
  3. 遍历结束后,n的值就是只出现一次的元素。
图解:
代码如下:
代码语言:javascript复制
//找单身狗1
int main()
{
	int n = 0;
	int arr[9] = { 1,2,3,4,5,1,2,3,4 };
	for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i  )
	{
		n = n ^ arr[i];//任何数和0异或就得到自己,与自己异或则为0
	}
	printf("%d", n);

寻找单身狗2

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

找出一个只出现过一次的数字的问题处理方法就是找一个数字把里面所有的数字都异或一遍,利用异或两次等于没异或的特点来处理。那么如果有两个数字都只出现了一次,那么如此得到的应该是两个数异或的结果。首先这个结果肯定不是0(要不然就全都配对了),所以里面一定至少一位是一。找出值为1的一位,以这一位的值将结果分为两组。例如1 2 3 4 1 2,异或完的结果应该是3^4得到的111,那么随便找一位就行了。例如找最低位,那么这一位是1的有1 3 1,是0的有2 4 2,由于是利用异或结果为1的某一位分的组,所以两个待查询数字一定分别在两组中。所以再找两个变量,分别异或两组数,即可找到这两个数。

图解:
代码如下:
代码语言:javascript复制
//找单身狗2
//1 2 3 4 5 1 2 3 4 6

//pnum1 和 pnum2 存储 你找到的这两个数据 n代表数组长度
void FindNum(int arr[], int len, int* pnum1, int* pnum2)
{
	//1.将整个数组异或起来,得到两个不同数字的异或结果 例如: 5^6
	int tmp = 0;
	for (int i = 0; i < len; i  )
	{
		tmp ^= arr[i];
	}
	//2.找到tmp中,二进制为1的某一位k 0110 0111 0001
	int k = 0;
	for (int i = 0; i < 32; i  )
	{
		if ((tmp >> i) & 1 != 0)
		{
			k = i;
			break;
		}
	}
	//3、遍历数组 把每个数据 第K为上是1的,分到一个组进行异或
	//最终的值存储到 pnum1 或者 pnum2 当中
	*pnum1 = *pnum2 = 0;
	for (int i = 0; i < len; i  )
	{
		if ((arr[i] >> k) & 1 != 0)
		{
			//第k位是1
			*pnum1 ^= arr[i];
		}
		else
		{	//第k位是0
			*pnum2 ^= arr[i];
		}
	}
}

int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int len = sizeof(arr) / sizeof(arr[0]);
	int num1 = 0;
	int num2 = 0;;
	FindNum(arr, len, &num1, &num2);
	printf("%d %d", num1, num2);
	return 0;
}

希望对你有帮助!加油!

若您认为本文内容有益,请不吝赐予赞同并订阅,以便持续接收有价值的信息。衷心感谢您的关注和支持!

0 人点赞