题目
【中等】BM52 数组中只出现一次的两个数字
描述
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
数据范围:数组长度 2≤n≤1000,数组中每个数的大小 0<val≤1000000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
提示:输出时按非降序排列
示例
输入:
[1,4,1,6]
返回值:
[4,6]
说明:
返回的结果中较小的数排在前面
思路
- 假如只有一个数字只出现一次,则将数组元素逐个异或,剩下来的那个数字即为所求数字
- 当有两个数字只出现一次时,数组元素逐个异或的结果是那两个数字的异或值。找到此异或值的最后一个 ‘1’ 所在的位置p,即为所找两个数字的最后一个不同位。
- 根据该位上数字的不同,将整个数组分成两组,具体做法是将数组元素与p相与(&)
- 分别在两组中逐个元素相异或,最后的结果即为所求两个只出现一次的数字
- 最后注意题目要求两个数字从小到大排序
代码
class Solution {
public:
vector<int> FindNumsAppearOnce(vector<int>& array) {
int xor_val = 0;
for(int num : array){
xor_val ^= num;
} //两目标元素的异或值
int p = 1;
while(!(p & xor_val)){
p <<= 1;
} //找到最后一个不同位
int a = 0;
int b = 0;
for(int num : array){
if(num&p){ //分组并组内异或
a ^= num;
}else{
b ^= num;
}
}
vector<int>ret;
if(a > b){
int c = a;
a = b;
b = c;
}
ret.push_back(a);
ret.push_back(b);
return ret;
}
};