问题描述
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例
示例1
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例2
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制
2 <= nums <= 10000
解题思路
这个题难在空间复杂度要达到O(1),这意味着我们不能使用另外一个数组来做(不然也太简单了)。看了题解后才会做的,我位运算练习的太少了。
首先我们考虑如果是一个数字只出现了一次,我们应该怎么做?自然是异或,从头异或到尾,结果就是那个数字。这是因为相同的数字异或会抵消掉。
那么两个数字呢,假设两个数字是a和b,最终结果是c,那么将c化为二进制就是 ,每一位都是对应a和b的异或值,关键就在于分组,将a与b分到两组中,并且其他的数据每一对都分到同一组中。
假设 ,那么我们知道 ,假设任选一个数据为x,那么我们可以当 的时候,放到一组, 的时候,放到另一组,这样每一对都放在一组里面了,同时保证了a和b不在同一个组中(因为当前位置 )。
完整代码
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int a=0,b=0,c=0,pos=1;
for (auto i:nums) c^=i;
while(!(pos&c)) pos<<=1;//找到从右边起第一个非0的位置
for (auto i:nums){
if(pos&i) a^=i;
else b^=i;
}
return vector<int>{a,b};
}
};