数组中找出两个只出现一次的数字

题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

思路:题目要求时间复杂度是O(n),空间复杂度是O(1),这说明基于比较的办法求解无法完成,这题需要异或的性质,异或(同为0,异为1,相当于不进位加法)

因为其它数都出现两次,当扫描完一次之后,将所有的数做异或,那些相同的数都会变成0,结果是两个不同的数的异或。例如,9,4,4,2做异或,4,4异或为0,结果就相当于9异或2。

这里有两个数字不同,假设只有一个数字不同,那么,我们只需要扫描一遍,所有数做异或就可以得出结果。有两个数字怎么办呢?思路就是将这两个数划分到两个不同的组去。

划分依据是什么呢?

1,可以这么做,先将所有的数异或起来,假设结果为11001100,那么可以用最低的1位划分(即第2位,低到高,从0数起)[实质上可以用任何一个1划分,只是这是最方便的],为什么1可以划分开两个不同的数呢?将两个数写成二进制的形式,那么异或结果显示出的1位(同时两个不同的数相异或必然有1,因为同则必为0),都是二者相应位不同的。(异为1,同为0),因此用1划分则不同的两数必然被分到两个不同组

2,第二步,将两个子数组的数做异或就能得出结果,因为相同的数会得0.

3,小技巧,中途需要判断位是否为1,方法是:先将要判断的位通过右移移到最末位,然后与0000.....00001做位与,末位是1,则结果是1,若末位是0,结果是0

代码:

 

/*一个整型数组里除了两个数字之外,其他的数字都出现了两次。
请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),
空间复杂度是O(1)*/
#include
using namespace std;
int FindFirstbitis1(int sum)//找到第一个位是1(右往左)的索引号
{
	int index=0;
	while((1 & sum)==0)//和000..00001做与,若末位为0,即等于0,若末位为1,即为1
	{
		sum=sum>>1;
		++index;
	}
	return index;
}
int judgeindexbitis1(int num,int index)
{
	num = num >> index;//右移index位,使要判断的一位处于最末位
	return(1 & num);//和000..0001与,1则返回1,0则返回0
}
void xor(int* A,int len)
{
	int sum=0;//两相异的数
	for(int i=0;i

 

 

 

 

 

你可能感兴趣的:(算法分析与设计,C++,面试题)