传送门:
136:https://leetcode-cn.com/probl...
56-I:https://leetcode-cn.com/probl...
对于第二题,问题看似简单,但是暗藏了“时间复杂度是O(n),空间复杂度是O(1)”这样的玄机。O(n)容易实现,但加上空间复杂度的要求就复杂得多。
考虑一下单个数的情况
即问题136,若只有一个只出现了一次的数字,该如何处理?
对于两个相同的数字,取异或后为0.同时任何数与0取异或为本身
1 | 0 | 1 | 1 |
---|---|---|---|
1 | 0 | 1 | 1 |
0 | 0 | 0 | 0 |
将问题推广至两个不同的数
1.将所有数字取异或等于两个结果(r1,r2)的异或.
2.异或结果来看,从右往左按位搜索第一个1.这里的目的是将r1,r2从位上区分开。至于为什么从右往左,将异或结果转换为二进制---一直对2取余;另外也可以使用移位操作,那样从左从右都是一样的.
3.现在就可以按这一位将输入数组分为该位为0、该位为1两组。相同的数字一定会分在一个组,r1,r2一定分落在两个组.
4.对两组取异或分别得出r1,r2.
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int numXor = 0;
//所有的异或,0^x = x
for(int i=0;i<nums.size();++i)
numXor ^= nums[i];
int index=0;
//取从右往左的第一个1
for(;numXor%2==0;index++,numXor/=2);
int a=0,b=0;
for(int i=0;i<nums.size();++i){
//按位右移index位.按该位分组
if (((nums[i] >> index) & 1) == 0)
a ^= nums[i];
else
b ^= nums[i];
}
return vector<int>{a, b};
}
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。