一个百度的面试题目

题目:一个数组中有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、付费专栏及课程。

余额充值