【找单身狗】(2只):一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。

一.找单身狗(1只)

我们或许之前就已经做过这样的题:

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

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

我们使用异或(^)可以很轻松地解决问题。

当两个相同的数字异或时,结果为0。

所以我们将所有的数字异或在一起,那么最后得到的结果就是那个只出现了一次的数字。

我们来看下面的代码。

#include

int find_single_dog(int* arr, int sz)
{
	int i = 0;
	int ret = 0;
	for (i = 0; i < sz; i++)
	{
		ret = ret^arr[i];
	}
	return ret;
}

int main()
{
	int arr[] = { 1,1,4,4,5,7,7,5,8,88,8 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int ans = find_single_dog(arr, sz);
	printf("%d\n", ans);

	return 0;
}

 

显然我们找到了单身狗。

【找单身狗】(2只):一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。_第1张图片

 二.找单身狗(2只)

那么,找一只单身狗这么轻松,找两只呢?

万法不离其宗。我们依然可以通过异或(^)来找到。

在这里,既然要找两只单身狗,那么我们可以将所有的数字按照一定的规则分为两组,这两组内分别异或,就找到了那两只单身狗。

好,我们接下来的重点就是讨论,按照什么样的规则呢?

找出一个只出现过一次的数字的问题处理方法就是找一个数字把里面所有的数字都异或一遍,利用异或两次等于没异或的特点来处理。

那么如果有两个数字都只出现了一次,那么如此得到的应该是两个数异或的结果。

首先这个结果肯定不是0(要不然就全都配对了),所以里面一定至少一位是一。

找出值为1的一位,以这一位的值将结果分为两组。(因为值为1时说明这两只单身狗在这一位上,一个为0,一个为1)

例如1 2 3 4 1 2,异或完的结果应该是3^4得到的111,那么随便找一位就行了。

例如找最低位,那么这一位是1的有1 3 1,是0的有2 4 2,由于是利用异或结果为1的某一位分的组,所以两个待查询数字一定分别在两组中。

所以再找两个变量,分别异或两组数,即可找到这两个数。 

#include

void FindTwoNum(int arr[], int n, int* pnum1, int* pnum2)
{
	int i = 0;
	int sum = 0;

	//先找到两个数互相异或的结果
	for (i = 0; i < n; i++)
	{
		sum ^= arr[i];
	} 

	int pos = 0;

	//再找到有分歧的一位。在这一位上,两个数一定是一个1 一个0
	for (i = 0; i < 32; i++)
	{
		if ((sum >> i) & 1)
		{
			pos = i;
			break;
		}
	} 

	for (i = 0; i < n; i++)
	{
		if ((arr[i] >> pos) & 1)
		{
			*pnum1 ^= arr[i]; //这一位是1的,放在数1里
		}
		else
		{
			*pnum2 ^= arr[i]; //这一位是0的,放在数2里
		}
	}
}

int main()
{
	int arr[] = { 1,1,4,4,5,7,77,7,5,8,88,8};
	int sz = sizeof(arr) / sizeof(arr[0]);
	int num1 = 0;
	int num2 = 0;
	FindTwoNum(arr, sz, &num1, &num2);

	printf("%d  %d\n", num1, num2);

	return 0;
}

这样我们就找到了两只单身狗。

【找单身狗】(2只):一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。编写一个函数找出这两个只出现一次的数字。_第2张图片

 

你可能感兴趣的:(C语言,算法,c语言)