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[] = {4, 5, 3, 4, 5, 7, 7, 6, 8, 8};
64 int odd1, odd2;
65 findOutTwoOdds(a, 10, odd1, odd2);
66 cout << odd1 << " " << odd2 << endl;
67 return 0;
68 }
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[] = {4, 5, 3, 4, 5, 7, 7, 6, 8, 8};
64 int odd1, odd2;
65 findOutTwoOdds(a, 10, odd1, odd2);
66 cout << odd1 << " " << odd2 << endl;
67 return 0;
68 }
在写代码的时候,最好不要起一些容易混淆的变量名。我在编写该程序的时候,就范了该错误,调了好久才调好!

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名小橋流水(包含链接)。如您有任何疑问或者授权方面的协商,请给我发邮件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述