题目要求时间复杂度是O(n),空间复杂度是O(1)。
异或可以将两个只出现一次的数筛选出来,之后再把这两个数分到两组中,并且将相同的数分到同一组,两组分别异或就能求出两个数。
异或规则是不相同为1,相同为0
所以利用a^b 的结果中为1的某一位作为判断依据
class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int res=0,a=0,b=0;
for(int i:nums){
res^=i;
}
int div=1;
//判断依据
while((div&res)==0){
div=div<<1;
}
for(int i:nums){
//因为a,b不同 所以和div与运算会有不同结果
if(div&i){
// cout<<"aaaa "<<i<<endl;
a^=i;
}
else{
// cout<<"bbbb "<<i<<endl;
b^=i;
}
}
return vector<int>{a,b};
}
};
剑指 Offer 56 - II. 数组中数字出现的次数 II
将所有数的每一位出现的次数相加 最终结果为3的倍数或者3的倍数余1
所以我们找出3的倍数余1的所有位就是出现一次的数
因为有些数出现三次 所以我们把三次用三种状态表示出来 分别为 00 01 10
出现次数相加 最后状态为 00或01 ‘也就是说我们要找出01状态的所有位
我们用one和two来表示 初始化one和two为0 表示00状态
比如说 n=3
n | 0 | 0 | 1 | 1 |
two | 0 | 0 | 0 | 0 |
one | 0 | 0 | 1 | 1 |
为什么最后返回one
因为最终状态为01 two这一位为0 所以只要返回one就行了
class Solution {
public:
int singleNumber(vector<int>& nums) {
int one=0,two=0;
for(int i:nums){
one=one^i&~two;
two=two^i&~one;
}
return one;
}
};