为了解决单身狗问题,我当了十八年单身狗,总结出来的两种方法……

434 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 所谓单身狗问题吗,翻译成数学语言,就是在已知的一串数字,存在数字只出现一次,其余的出现两次的问题。 在这里,我用我现有的知识,为大家提供了两种解决办法。

第一种1.0:就是大家耳熟能详的将所有数字异或在一起 这种方式主要利用了按位异或的以下三点: 1.异或满足交换律

2.相同数字异或结果为0

3.0和任何数字异或都是0

通过这个方法,单独的数字便会被留下。

{
	int dog = 0;
	for (int i = 0; i < lenth; i++)
	{
		dog ^= nums[i];
	}
	printf("单身狗为编号:%d\n", dog);
}

但很明显,这种方法仅仅只能处理单只单身狗,但是单身狗怎么可能只有一只呢。如果有两只呢?好接下来我们来看如何处理两只单身狗。

image.png

第一种2.0(进阶)

我们知道,如果存在两只单身狗a和b,最终异或下来的结果便是a^b,再结合异或的特点:相同为0,相异为1。举个例子:

a = 5; 二进制序列:00000000000000000000000000000101;
b = 2; 二进制序列:00000000000000000000000000000010;
a^ b == 7;二进制序列:00000000000000000000000000000111;

观察上面式子,不难发现异或结果为1的地方就是两个数二进制位不同的地方,这样我们就可以通过异或结果为1的位置,对原数据进行分两类(该位置为1或0),这样每边就只有一只单身狗啦!这样再套用1.0的方法即可

{
	int dogs = 0;//单身狗们(即两只单身狗异或的结果)
	int offset = 0;//作为分类界限的二进制位的位置
	int dog1 = 0;
	int dog2 = 0;
	for (int i = 0; i < lenth; i++)
	{
		dogs ^= nums[i];
	}
	for (int i = 0; i < 32; i++)
	{
		if ((dogs >> i) % 2 == 1)//找到两个数不同的一位
		{
			offset = i;
			break;
		}
	}
	for (int i = 0; i < lenth; i++)
	{
		if ((nums[i] >> offset) % 2 == 1)
		{
			dog1 ^= nums[i];
		}
		else
			dog2 ^= nums[i];
	}
	printf("两只单身狗的编号分别为:%d %d\n", dog1, dog2);
}

这样就解决了两只单身狗的问题。
道德经中说过:“一生二,二生三,三生万物”(虽然没啥关系),所以单身狗也不可能只有两只,那如何处理多只呢?

image.png

接下来我提出了更泛用的方法。

第二种

利用哈希表的思想,来处理。

主要方法是通过创建一个大小为2*lenth的一维辅助数组haxmap(设待查数组长度为lenth),haxmapi用于存储待查数组中的值,haxmap[i+lenth]用于存储对应值出现的次数。 存储待查数组对应值时,这时需要有一个count变量记录已填入的待查数组中的值的个数。因此每次需要遍历比较haxmap数组前count的值中有无相同的,如果有直接在其对应位置(该位置+lenth)加1,没有便直接在haxmap[count]填入且haxmap[count+lenth]+1. 最后只需遍历后lenth个元素,找到为1的值,便打印其前lenth的对应值即可。

{
	int dogs = 0;//单身狗们(即两只单身狗异或的结果)
	int offset = 0;//作为分类界限的二进制位的位置
	int dog1 = 0;
	int dog2 = 0;
	for (int i = 0; i < lenth; i++)
	{
		dogs ^= nums[i];
	}
	for (int i = 0; i < 32; i++)
	{
		if ((dogs >> i) % 2 == 1)//找到两个数不同的一位
		{
			offset = i;
			break;
		}
	}
	for (int i = 0; i < lenth; i++)
	{
		if ((nums[i] >> offset) % 2 == 1)
		{
			dog1 ^= nums[i];
		}
		else
			dog2 ^= nums[i];
	}
	printf("两只单身狗的编号分别为:%d %d\n", dog1, dog2);
}

感谢观看!!!如有错误,欢迎指正!