S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

题目描述:

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;
}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yysdsyl/archive/2009/06/22/4289828.aspx


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理