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

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


可能大家都见识过找出一个只出现一次的数,直接把所有的数异或就可以了,最终的结果就是这个数了。但是如果出现两个这样的数,那又将如何呢?

 

假如这两个数为a和b,那么将所有的数异或得到的数必定为a^b。由于a和b不相等,那么a^b != 0,也就是说在a^b中必定至少有一位为1,对应位上a与b不一样,根据这一位,我们可以将a和b分开,并将数分成两组。注意,两个相同的数肯定会被分到同一个组。这样,分别对每一组进行取异或,就能求出这两个数了。

 

代码如下:

代码
 1 /* 
 2  * File:   main.cpp
 3  * Author: ziqiao
 4  *
 5  * Created on 2011年3月17日, 下午12:05
 6  */
 7 
 8 #include <cstdlib>
 9 #include <iostream>
10 
11 using namespace std;
12 
13 int findOutOneOdd(int a[], int n)
14 {
15     int result = a[0];
16     for (int i = 1; i < n; i++)
17         result ^= a[i];
18     return result;
19 }
20 
21 void findOutTwoOdds(int a[], int n, int &odd1, int &odd2)
22 {
23     int x = findOutOneOdd(a, n);
24     int i;
25     for (i = 1; i != 0 ; i <<= 1)
26     {
27         if (x & i != 0)
28             break;
29     }
30     if (i == 0)
31         throw "input is illeagle";
32     bool flag1 = false,  flag2 = false;
33     for (int j = 0; j < n; j++)
34     {
35         if (a[j] & i != 0)
36         {
37             if (!flag1)
38             {
39                 odd1 = a[j];
40                 flag1 = true;
41             }
42             else
43              odd1 ^= a[j];
44         }
45         else
46         {
47             if (!flag2)
48             {
49                 odd2 = a[j];
50                 flag2 = true;
51             }
52             else
53                 odd2 ^= a[j];
54         }
55     }
56 }
57 
58 /*
59  * 
60  */
61 int main(int argc, char** argv)
62 {
63     int a[] = {4534577688};
64     int odd1, odd2;
65     findOutTwoOdds(a, 10, odd1, odd2);
66     cout << odd1 << " " << odd2  << endl;
67     return 0;
68 }

 

在写代码的时候,最好不要起一些容易混淆的变量名。我在编写该程序的时候,就范了该错误,调了好久才调好!

posted on 2011-03-17 05:26  小橋流水  阅读(270)  评论(0编辑  收藏  举报

导航