• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
james1207

博客园    首页    新随笔    联系   管理    订阅  订阅

一个整数数组里面,除了两个数之外,其他的数字都出现了两次,写一个程序找出这两个数

一个整数数组里面,除了两个数之外,其他的数字都出现了两次,写一个程序找出这两个数,要求算法的时间复杂度为O(n).

n为数组的长度。

 

程序代码如下:

//取二进制中首个为1的位置
int findFirstOne(int value)
{     
	int pos = 0;
	while ((value&1) != 1)
	{
		value = value>>1;
		pos++;
	}
	return pos;
}

//测试某位置是否为1
char testBit(int value, int pos)
{  
	return ((value>>pos)&1);
}

int findNums(int date[], int length, int *num1, int *num2)
{
	if (length < 2)
	{
		return -1;
	}
	
	int ansXor=0;
	int i = 0;
	int pos = 0;
	
	for (i=0; i<length; i++)
	{
		ansXor ^= date[i];               //异或
	}
	
	pos = findFirstOne(ansXor);
	
	*num1 = *num2 = 0;
	
	for(i=0; i<length; i++)
	{	
		if (testBit(date[i], pos))
		{    
			*num1 ^= date[i];
		}
		else
		{
			*num2 ^= date[i];
		}
	}
	
	return 0;
}

1、首先第一次遍历整个数组,找出不同的那两个数的异或后的结果,见下面这段代码.

for (i=0; i<length; i++)
{
	ansXor ^= date[i];               //异或
}

2、找到异或结果中ansXor中用移位的方式找到第一个二进制数中为1的位置,这个很关键,找到这个位置后,说明在该位置上,这两个不同的数中,一个为0,一个为1,这个应该可以理解对吧?

//取二进制中首个为1的位置
int findFirstOne(int value)
{     
	int pos = 0;
	while ((value&1) != 1)
	{
		value = value>>1;
		pos++;
	}
	return pos;
}


 

我们把这个位置记为pos

3、然后再遍历一次数组,把这个数组分成两个子数组,pos位上为1的,和pos位上为0的
for(i=0; i<length; i++)
{	
	if (testBit(date[i], pos))
	{    
		*num1 ^= date[i];
	}
	else
	{
		*num2 ^= date[i];
	}
}

这里借助了异或的原理,pos位置上为1的其它成双成对的数肯定也是为1的,同理,pos位上为0的时也一样。

上面程序思路是我参考别人思路编写的代码,欢迎大家提出好的思路,一起学习一起进步!

 

posted @ 2013-08-22 18:30  Class Xman  阅读(308)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3