剑指Offer - 九度1351 - 数组中只出现一次的数字
2013-11-23 01:23
- 题目描述:
- 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
- 输入:
-
每个测试案例包括两行:第一行包含一个整数n,表示数组大小。2<=n <= 10^6。第二行包含n个整数,表示数组元素,元素均为int。
- 输出:
- 对应每个测试案例,输出数组中只出现一次的两个数。输出的数字从小到大的顺序。
- 样例输入:
-
8 2 4 3 6 3 2 5 5
- 样例输出:
-
4 6
题意分析:
题目要求找出两个只出现一次的数,其他数都出现了两次。如果是一个数只出现一次的话,那全部xor之后就是结果了。
对于两个数,情况还是比较特殊的。因为两个数a和b,c = a ^ b;则c表示的就是a和b不同的位,树状数组的lowbit操作比较方便,取bit = c & (-c)。从其中随便取一位就可以将数组分为两拨儿,一拨儿这位是0,另一拨儿是1。对于那些成双的数字,总会落在同一堆里,依然是做xor,成对的数字消除掉,剩下的两个结果就是那两个数了。
扫描一遍,时间复杂度O(n),空间复杂度O(n)。
不过,要是有三个数只出现一次呢?要是其他数都出现三次呢?
当然,通用的笨办法肯定有:扫一遍统计每个元素出现的次数,用map来存统计结果。时间复杂度O(nlog n),空间复杂度O(n)。
1 // 652741 zhuli19901106 1351 Accepted 点击此处查看所有case的执行结果 4540KB 799B 790MS 2 // 201311171920 3 #include <cstdio> 4 using namespace std; 5 6 int main() 7 { 8 int *a = NULL; 9 int n, i; 10 int r1, r2; 11 int r; 12 int bit; 13 14 while(scanf("%d", &n) == 1){ 15 if(n <= 0){ 16 continue; 17 } 18 19 a = new int[n]; 20 21 for(i = 0; i < n; ++i){ 22 scanf("%d", &a[i]); 23 } 24 r = 0; 25 for(i = 0; i < n; ++i){ 26 r ^= a[i]; 27 } 28 // not necessarily the lowbit, any bit with value '1' can be the pivot bit. 29 bit = r & (-r); 30 31 r1 = r2 = 0; 32 for(i = 0; i < n; ++i){ 33 if((a[i] & bit) != 0){ 34 r1 ^= a[i]; 35 }else{ 36 r2 ^= a[i]; 37 } 38 } 39 40 if(r1 > r2){ 41 r1 ^= r2 ^= r1 ^= r2; 42 } 43 44 printf("%d %d\n", r1, r2); 45 46 delete[] a; 47 a = NULL; 48 } 49 50 return 0; 51 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)