您的位置:首页 > 职场人生

面试题精选:找出数组中只出现一次的3个数

2011-05-04 16:31 369 查看
题目描述:

Given an array of n integers, such that each number in the array appears exactly twice, except for three numbers (say a, b and c) which appear exactly once.

In O(n) time and O(1) space find a,b and c.

分析:

先看这样一道题:

n个数中有且仅有一个数出现了奇数次(其它数都出现了偶数次),如何用线性时间常数空间找出这个数。

解法如下:

从头到尾异或一遍,结果就是要求的那个数。(原理很清楚明了)

再看稍微加强版:

n个数中有且仅有两个数出现了奇数次(其它数都出现了偶数次),如何用线性时间常数空间找出这个数。

解法比较巧妙,主要思想是将元素分成两组,每组中有且仅有一个数出现了奇数次(其它数都出现了偶数次),然后应用上题的结论解答,至于如何分组,见下:

1、异或所有元素得xors

2、找出xors中不为0的一个bit位(通常从右向左找出第一个不为0的)

3、以2中找到的bit位为sentinel,将数组分为两组

本题:

思路类似于求解上题,关键是找出第一个来,然后借助上题结论求另外两个

// Let s = a ^ b ^ c. We know that s not in (a, b, c),
// since if s == a, say, then b ^ c == 0 and b == c.
// Let f(x) be the lowest bit where x differs from s.
// The algorithm computes flips = f(a) ^ f(b) ^ f(c),
// since the numbers appearing an even number of times cancel.
// The variable flips has parity 1, so it is non-zero,
// and lowbit(flips) is a bit where one or three of a, b, c
// differ from s. It can't be three, however, so the final
// exclusive-or includes exactly one of a, b, c.

代码:

#include <iostream>

using namespace std;

// get lowest different bit
int lowbit(int x)
{
return x & ~(x - 1);
}

// Given an array of n integers, such that each number
// in the array appears exactly twice, except for two
// numbers (say a and b) which appear exactly once.
//
// In O(n) time and O(1) space find a and b.
// e.g.
// { 2 3 3 2 4 6 4 7 8 8 } ---> a/b = { 6 7}
void Find2(int seq[], int n, int& a, int& b)
{
////XOR
int xors = 0;
for(int i = 0; i < n; i++)
xors ^= seq[i];

////get different bit
int diff = lowbit(xors);

////
a = 0;
b = 0;
for(int i = 0; i < n; i++)
{
if(diff & seq[i])
a ^= seq[i];
else
b ^= seq[i];
}
}

// Given an array of n integers, such that each number
// in the array appears exactly twice, except for three
// numbers (say a, b and c) which appear exactly once.
//
// In O(n) time and O(1) space find a,b and c.
// e.g.
// { 2 3 3 2 4 6 4 7 8 8 1 } ---> a/b = { 6 7 1}

// Let s = a ^ b ^ c. We know that s not in (a, b, c),
// since if s == a, say, then b ^ c == 0 and b == c.
// Let f(x) be the lowest bit where x differs from s.
// The algorithm computes flips = f(a) ^ f(b) ^ f(c),
// since the numbers appearing an even number of times cancel.
// The variable flips has parity 1, so it is non-zero,
// and lowbit(flips) is a bit where one or three of a, b, c
// differ from s. It can't be three, however, so the final
// exclusive-or includes exactly one of a, b, c.

void Find3(int seq[], int n, int& a, int& b, int& c)
{
////XOR
int xors = 0;
for(int i = 0; i < n; i++)
xors ^= seq[i];

////
int flips = 0;
for(int i = 0; i < n; i++)
flips ^= lowbit(xors ^ seq[i]);
flips = lowbit(flips);

////get one of three
a = 0;
for(int i = 0; i < n; i++)
{
if(lowbit(seq[i] ^ xors) == flips)
a ^= seq[i];
}

////swap a with the last element of seq
for(int i = 0; i < n; i++)
{
if(a == seq[i])
{
int temp = seq[i];
seq[i] = seq[n - 1];
seq[n - 1] = temp;
}
}

////call Find2() to get b and c
Find2(seq, n - 1, b, c);
}

int _tmain(int argc, _TCHAR* argv[])
{
int a,b,c;
int test1[] = { 2, 3, 3, 2, 4, 6, 4, 7, 8, 8 };
Find2(test1, 10, a, b);
cout<<"a = "<<a<<" , b = "<<b<<endl;

int test2[] = {1 , 2 , 3 };//{ 2, 3, 3, 2, 4, 6, 4, 7, 8, 8, 1 };
Find3(test2, 3, a, b, c);
cout<<"a = "<<a<<" , b = "<<b<<" , c = "<<c<<endl;
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐