40、数组中只出现一次的数字

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

leetcode对应题目:

136. 只出现一次的数字 (只有一个数字出现一次)                                      题目解答

137. 只出现一次的数字 II(只有一个出现一次,其余出现3次)               题目解答

260.只出现一次的数字 III(有两个数字出现了一次)                                    题目解答

268.缺失的数字                                                                                         题目解答

总结:别人写的很详细了哈!我就不露怯了。关键点就是利用异或运算,然后根据不同题目的一点儿改动。这种题目大家一开始都会想到用哈希表,但是这就相当于做题没有充分利用给定的条件,如果这时候面试官对时间复杂度,空间复杂度有要求的话就糟糕了。

异或的性质:任何一个数字异或它自己都等于0.

“268缺失的数字”一题,实际上就是一个数组只有一个数出现一次,其余数出现两次的思想,只是因为题目给定数字范围"0~n"这样就可以正好利用for(...)循环中的数字相异或。注意!是从1~n还是从0~n,写法上要注意一点。不过核心就是要把0~n或者1~n的数字都相异或了。

其实最关键的是:为什么凭借n&~n就能找到一个区分两个只出现一次的数字?

首先要知道n&~n的意义是如何求一个二进制数的最低位的1在哪里

又因为这个数是根据只出现一次的数a,b异或而来,也就是说最低位的1肯定是a,b的最低位异或来的,就是说a,b之间肯定有一个最低位是0,一个是1,所以根据这种情况就能分开这两个数了。

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        if(!data.size())    return ;
        int dif = 0;
        for(int i = 0;i<data.size();i++){
            dif ^= data[i];
        }
        dif &= -dif;//进行 a &= -a 操作。首先变负数吧,在二进制中负数采用补码的形式,而补码就是反码 +1
                    //这个操作之后可以找到两个不相同数的不相同的位.
                    //比如1,1,2,2,...,3,5,dif = 110 dif &= -dif dif = 010 
                    //可知3 和 5 在从低位开始的第二位不同.010
                    //所以根据这一位的差异来区别两个数
        for(int i = 0;i<data.size();i++){
            if(dif &  data[i])
                *num1 ^=  data[i];//其它成对出现的数异或两次不变。剩下就是单独出现的。
            else
                *num2 ^=  data[i];
        }
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值