一个百度的面试题目

题目:一个数组中有2个数只出现了一次,其他的数都出现了两次,写一个算法找出这两个只出现一次的数

分析:该题目可以通过异或完成,先让我举一个例子

4:0100

^5:0101

-------------

1: 0001

^5:0101

-------------

4:0100

上面的例子说明4^5^5=4;同理4^5^4=5

int find_first_1(int n)
{
int index = 1;
while( (n&1)==0)
{
n >>= 1;
index <<= 1;
}
return index;
}

这个函数的返回值index比如如果num=1100,那么index=0100=4

for(int i=0;i<len;i++)
{
if((arr[i]&index)==0)
num1^=arr[i];//其实就是分组
else
num2^=arr[i];
}

这个函数是进行分组

我打个比方: 1 1 2 2 5 3 ,那么互相异或以后的值temp=6(0110),那么返回的index=2

那么1 1 2 2 5 3 分别与2相与则为0000 ,0000,0010,0010,0000,0010,那么我们将最后一个为0的分为一组,将最后一个位为1的分为另外一组

最后为0的那组:1,1,5,

最后不为0的那组:2,2,3

然后组与组之间的元素互相以后

组0 最后异或结果为5

组1最后异或结果为3:

这样就找到了数组中这两个只出现一次的数,下面贴出代码:

// find_first_1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
//寻找数组中两个单独出没的数字
int find_first_1(int n)
{
int index = 1;
while( (n&1)==0)
{
n >>= 1;
index <<= 1;
}
return index;
}
void find(int * arr, int len, int & num1, int & num2)
{
int temp = 0;
for(int i=0;i<len;i++)
temp ^= arr[i];
unsigned int index = find_first_1(temp);

num1 = 0;
num2 = 0;
for(int i=0;i<len;i++)
{
if((arr[i]&index)==0)
num1^=arr[i];//其实就是分组
else
num2^=arr[i];
}
}

int main()
{
int num1,num2;
//int arr[] = {2,2,2048,1024,4,5,4,5};
int arr[]={1 ,1, 2, 2, 5, 3 };
find(arr,8,num1,num2);
printf("%d %d\n",num1,num2);

cout<<endl;
system("pause");
return 0;
}


// find_first_1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
//寻找数组中两个单独出没的数字
int find_first_1(int n)
{
	int index = 1;
	while( (n&1)==0)
	{
		n >>= 1;
		index <<= 1;
	}
	return index;
}
void find(int * arr, int len, int & num1, int & num2)
{
	int temp = 0;
	for(int i=0;i<len;i++)
		temp ^= arr[i];
	unsigned int index = find_first_1(temp);

	num1 = 0;
	num2 = 0;
	for(int i=0;i<len;i++)
	{
		if((arr[i]&index)==0)
			num1^=arr[i];//其实就是分组
		else
			num2^=arr[i];
	}
}

int main()
{
	int num1,num2;
	//int arr[] = {2,2,2048,1024,4,5,4,5};
	int arr[]={1 ,1, 2, 2, 5, 3 };
	find(arr,8,num1,num2);
	printf("%d %d\n",num1,num2);

	cout<<endl;
	system("pause");
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值