260. Single Number III

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

Note:
The order of the result is not important. So in the above example, [5, 3] is also correct.
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

s思路:
1. 出现一次。之前遇到题目是只有一个数出现一次,其他都是两次,那就用xor来cancel out。现在要求提高了,有两个数只出现一次,也要找出来。
2. 这让我联想到用moore voting algorithm,当一个数出现频率大于n/2时的方法应用到出现n/3时,如何推广的方法。这题还是用xor,但是需要更多的变量来保留细节,让我们能深入去找差别,除了xor,还需要一个变量来区别,因为毕竟是两个数字。
3. 比如nums = [1, 2, 1, 3, 2, 5],为了看到更多细节,把不同的数字3,5写成二进制:011和101,可以看出第2位不同,也就是如果我们对所有数的第二位是1还是0进行统计,如果1和0的个数都是奇数,说明在在这一位上可以区别开3和5,把3和5分到不同的group,然后分别在两堆里用xor就可以!
4. 看到更多细节,尤其是bit操作,看一个数看不出差别,那是因为看的整体,看问题看到最深入最深入也就到了数的最小单位,bit,所以如果自己没看出解法,是因为看问题的层次不对,不是太高,就是太低,想看到最低层次,要是解决起来容易,那就最低层次解决;如果到最低层次很繁琐,那就往高层次看,比如数学!

//方法1:深入大bit比较,不要在数字相同与否上逗留!
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        //
        int base;
        for(int i=0;i<31;i++){
            int zero=0,one=0;
            base=(1<<i);
            for(int num:nums){
                if(num&base) one++;
                else zero++;
            }    
            if(zero%2==1&&one%2==1) break;
        }
        int num1=0,num2=0;
        for(int num:nums){
            if(num&base){
                num1=num1^num;  
            }else
                num2=num2^num;    
        }
        return {num1,num2};
    }
};


//方法1.1:优化了代码,不用一个bit一个bit来bottom-up的从细节入手,从top-down试试:top-down就是从数学来把握!两个角度看问题而已!
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        //
        int xorAll=0;
        for(int k:nums){
            xorAll^=k;  
        }
        xorAll=xorAll&(xorAll^(xorAll-1));//这句太妙!例如xorAll=0b110110,说明在第二位就有不相同的bit,经运算后,就得到xorAll=0b000010,
        //这个运算就得到从右往左第一个1的位置,并把其他位清零

        int num1=0,num2=0;
        for(int k:nums){
            if(k&xorAll){
                num1=num1^k;    
            }else
                num2=num2^k;    
        }
        return {num1,num2};
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值