如何用C语言找到单身狗

1.问题描述

当我们拥有一对数组

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

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

例如:

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

只有5出现1次,要找出5这只单身狗。

2.解决方案

2.1:暴力求解

我们可以直接遍历整个数组两次,只出现的数组记录出来,这样就可以算出只出现过一次的数组了。

#include <stdio.h>

void find_single_dog1(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
			{
				int floag = 2;
				for (int j = 0; j < sz; j++)
				{
					if (arr[i] == arr[j])		//当两次遍历会出现的相同时计数加一
					{
						floag--;
					}
					if (floag == 1&&j==sz-1)	//当第二次遍历到最后一个数组这个数字还是只出现一次
					{
						printf("%d", arr[i]);
					}
				}
			}

}


int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4};
	int sz = sizeof(arr) / sizeof(arr[0]);
	find_single_dog1(arr, sz);

	return 0;
}

5

2.1:方案优化(异或)

如果我们认识异或(^)这个符号的话我们可以知道:

二进制位:

  • 相同为0
  • 相异为1

所以我们可以知道当一个数异或自己为0

当一个数异或0时就不变

int main()
{
	int a=5;
	printf("%d\n", a ^ 0);
	printf("%d\n", a ^ a);

	return 0;
}

5
0

这样当我们把这些出现两次的数字异或起来,那么最后变成了0,再异或一次我们的“单身狗”,就可以得出我们单身狗的数值。

所以我们可以把代码优化为这样,将数组遍历一次就够了,再进行异或:

void find_single_dog1(int arr[], int sz)
{
	int ret = 0;
	for (int i = 0; i < sz; i++)
	{
		ret = ret ^ arr[i];
	}
	printf("%d", ret);
}


int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4};
	int sz = sizeof(arr) / sizeof(arr[0]);
	find_single_dog1(arr, sz);

	return 0;
}

5

3.题目升级


当我们拥有一对数组

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

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

例如:

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

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

如果还是将所有的数异或起来,那么最后得到数就为5^6的结果,这样我们无法正确得出结果

3.1:分组讨论

使用数字异或做不到,那么我们感觉根据分组把两个需要异或的数字分开,并且每个相同的数字也在同一个组,这样分组异或就可以得出正确的结果

3.2:分组方法

既然要分组那么我们就要找出5和6的区别,当我们从二进制上看来看,5的二进制(101)和6的二进制(110)我们可以发现在第二个二进制中一个是1 一个为0,利用这个特征,我们就可以也把数组其余的数按这种分类方法分为(1 1 3 3 5) (2 2 4 4 6)

3.2:代码实现

既然涉及到了二进制位置,我们想起移位操作符,就可以知道,我们将数向右移动一位,再判断是否为1或0就可以实现代码了。

void find_single_dog2(int arr[], int sz)
{
	int ret = 0;
	for (int i = 0; i < sz; i++)
	{
		ret = ret ^ arr[i];
	}
	//分组
	int dog1 = 0;
	for (int i = 0; i < sz; i++)
	{
		if ((arr[i] >> 1) & 1 == 1)
		{
			dog1 = dog1 ^ arr[i];
		}
	}
	int dog2 = ret^dog1;	//dog1已经得出为6 再让他异或5^6(6^5^6)得到的数就为5
	//int dog2 = 0;


	//for (int i = 0; i < sz; i++)
	//{
	//	if ((arr[i] >> 1) & 1 != 1)
	//	{
	//		dog2 = dog2 ^ arr[i];
	//	}
	//}
	printf("%d %d", dog1, dog2);	
}


int main()
{
	int arr[] = { 1,2,3,4,5,6,1,2,3,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	find_single_dog2(arr, sz);

	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值