出现一次的数字(找单身狗)

在这里插入图片描述

  • 这里我们首先了解二进制数位异或的一些性质

  • 1.相同数字异或为0.(0 ^ 0 = 0, 1 ^ 1 = 0)

  • 2.相反数字异或为1.(1 ^ 0 = 1)

  • 3.和 0 异或结果不变( 1 ^ 0 = 1 , 0 ^ 0 = 0)

  • 4.和 1 异或结果相反( 1 ^ 1 = 0, 0 ^ 1 = 1)
    不妨将其推广到十进制数当中:

  • 1.相同的十进制数异或结果为 0

  • 例如:5 ^ 5 = 0

在这里插入图片描述

  • 2.两个大小不同的数字异或之后结果一定不是0
  • 例如: 3 ^ 5 = 6
    在这里插入图片描述
  • 3.和 0 异或结果不变
    在这里插入图片描述

对于这个问题,假设给定的数组是 [ 1,3,3,4,4,6]
大体的思路就是将数组根据1和6的某一位比特位不同分成两组。得到这样的两组数:
第一组: 1,3,3
第二组: 6,4,4
在这里插入图片描述
代码如下:

/**
* Note: The returned array must be malloced, assume caller calls free().
*/

int* singleNumbers(int* nums, int numsSize, int* returnSize){
    
    
	//通过异或数组当中的每个元素求出那两个数字异或的结果ret ,ret != 0
	//那么ret的二进制序列中一定有一位是 1(即:这两个数字的二进制序列在该比特位上一个是1 另一个是0) 
	//将该位是1的分为一组,是0的分为一组,再将这两组数分别异或即可的到最终结果。
	int ret = 0;
	
	for (int i = 0; i < numsSize; i++)
	{
    
    
		ret ^= nums[i];//ret是两个只出现一次的数异或的结果
	}
	int pos = 0;
	while (pos < 31)
	{
    
    
		if (ret & (1 << pos)) // ret按位与 1 << pos 位来判断哪一比特位是1。
		{
    
    
			break;
		}
		pos++;
	}//最终得到的pos就是那两个只出现一次的数比特位不同的那一位
	int *returnNums = (int *)malloc(sizeof(int)* 2);//存放只出现一次的那两个数
	returnNums[0] = 0;
	returnNums[1] = 0;// 初始化为0 .因为任何书异或0都是它本身
	for (int i = 0; i < numsSize; i++)
	{
    
    
		if (nums[i] & (1 << pos))
		{
    
    
			returnNums[0] ^= nums[i];//数组当中第pos位不是0的数异或得到结果
		}
		else
		{
    
    
			returnNums[1] ^= nums[i];//数组当中第pos位是0的数异或得到结果
		}
	}
	*returnSize = 2;
	return returnNums;
}

猜你喜欢

转载自blog.csdn.net/weixin_50168448/article/details/110953899