寻找单独出现的数——通用技巧

Posted 午饭要阳光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寻找单独出现的数——通用技巧相关的知识,希望对你有一定的参考价值。

请使用最快的方法,寻找单独出现的数。
例1:在一组数据中,只有一个数出现一次,其余数都出现两次,请找出这个单独出现的数。
例2:在一组数据中,只有一个数出现一次,其余数都出现三次,请找出这个单独出现的数。
例3:在一组数据中,只有一个数出现一次,其余数都出现四次,请找出这个单独出现的数。
例4:在一组数据中,只有一个数出现一次,其余数都出现五次,请找出这个单独出现的数。
...........

分析:
 像这种问题都可以通过排序来解决,但是毫无疑问,排序不是最快的方法。针对例1,大部分人都能想到,将所有数字全部异或,最后剩下来的数就是单独出现的数。但是问题一但升级,这种方法就行不通了,那么有没有一种通用的方法来解决这类问题呢???答案肯定是有的!!!

算法:
  既然这组数据中除了一个数出现一次外,其余数都出现了n次,借助一个bit[32] ,我们可以把这组数据中所有数据的第一个bit位统计出来加到一起放到bit[0]里面,以此类推,直到把所有bit位统计完为止。既然除一个数外其余数都出现n次,那么bit[i]%n所得到的结果就是单独的数中相应bit位上的结果。

以例2为例,有以下代码:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>


int check_along_num(int *arr,int len)
{
	assert(arr);
	int bit[32] = { 0 };                   
	int i = 0;
	int j = 0;
	int ret = 0;
	for (i = 0; i < len;i++)
	{
		for (j = 0; j < 32;j++)
		{
			bit[j] += ((arr[i] >> j)&1);        //统计数组中所有元素每一位上1的个数之和
		}
	}
	for (i = 0; i < 32;i++)
	{
		ret+=((1<<i)&((bit[i] % 3)<<i));         //出现三次的数,在bit[]中对应位上是3的倍数
	}
	return ret;
}
int main()
{
	int arr[10];
	for (int i = 0; i < 10;i++)
	{
		scanf("%d",&arr[i]);
	}
	int sz = sizeof(arr)/sizeof(arr[0]);
	int ret=check_along_num(arr,sz);
	printf("%d\n",ret);
	system("pause");
	return 0;
}


以上是关于寻找单独出现的数——通用技巧的主要内容,如果未能解决你的问题,请参考以下文章

VS中添加自定义代码片段——偷懒小技巧

求单独出现的数,strncpy的优化

趣题:寻找出现了奇数次的数

基于快速排序,寻找众数(出现最多的数),运用分治的思想

VS2015使用技巧 打开代码片段C#部分

Eclipse 中的通用代码片段或模板