码迷,mamicode.com
首页 > 编程语言 > 详细

求数组中出现一次的数字

时间:2015-05-17 23:38:01      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:c++

一个数组中只有一个数字出现一次,其余别的数字都出现两次,如何求出这个出现一次的数字?例如数组a[11]={1,2,2,3,3,4,4,5,5,6,6},则出现一次的是1,通过异或算法即可求出.

代码如下:

int onediffent(int a[],int n)
{
	int temp=0;
	for(int i=0;i<n;i++)
		temp=temp^a[i];

	printf("%d\n",temp);

}

补充:任何数与零异或等于任何数.任何数与自己相异或为0;

假如问题变成一个数组中有两个数字出现一次,其余别的数字都出现两次,那么如何求出这两个数字呢?

算法思路:首先将数组中的一组数字异或,结果存在temp中,然后计算出temp中最低位出现的位置,然后再和数组中所有的数字相与,这样就将数组分成了两个数组,问题转换为一个数组中只有一个数字出现一次的情况。
代码如下:

int twodiffent(int a[],int n)
{
	int temp,count,i,j,k;
	temp=a[0];
	j=k=0;
	int b[n],c[n];

	for(int i=1;i<n;i++)
		temp=temp^a[i];

	count=1;
	//求出temp中为1的最低位位置
	while(!(temp&1))
	{
		temp=temp>>1;
		count*=2;
	}
	//将两个数字分别分到两个数组中,问题转换为一个数组中只有一个出现一次的数.
	for(i=0;i<n;i++)
	{
		if(a[i]&count==1)
			b[j++]=a[i];
		else
			c[k++]=a[i];
	}
	onediffent(b,j);
	onediffent(c,k);
}
在算法群里某热心网友不吝赐教得到目前最优解,相对比算法二优化了至少一个世纪<囧>,代码如下:

void solve(int num[],int n)
{
        int x = 0;
        for(int i = 0; i < n; ++i)
        {
            x = x ^ num[i];
        }
        int smallestOne = x & -x;
        int a = 0;
        int b = 0;
        for(int i = 0; i < n; ++i)
        {
            if((num[i] & smallestOne) != 0)
                a = a ^ num[i];
            else
                b = b ^ num[i];
        }
       printf("%d %d\n",a,b);
}

该算法中x&-x是算出最低位的1,负数在计算机中是以补码表示,例如4&-4=4,1000&-1000=8 表示数字4中二进制位1最低位是在权为2^2出现,数字1000二进制位1最低位是在权值为2^3出现.算法二中的数组完全没有必要使用,空间复杂度为O(1),时间复杂度O(n);

如果你有更好的方法,不妨在此讨论.


求数组中出现一次的数字

标签:c++

原文地址:http://blog.csdn.net/persever/article/details/45799307

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!