[LeetCode][算法初级][数组] 25.只出现一次的数字

25 只出现一次的数字

https://leetcode-cn.com/explore/interview/card/top-interview-questions-easy/1/array/25/

用到异或去重的方法。异或(^)运算有如下性质:

  1. 交换率 a^b = b^a
  2. 结合律 a^b^c = a^(b^c)
  3. a^a=0; a^0=a; a^(-1)=~a;

去重利用的当然是a^a=0,a^0=a这2条性质了。题中的数组除了一个数只出现1次以外,其他数都出现2次,

不难理解只要把数组元素挨个异或,最后得到的结果就是那个落单的数字了。

int singleNumber(int* nums, int numsSize) {
    int i=0;
    int res=0;
    for(;i<numsSize;i++){
        res^=nums[i];
    }
    return res;
}

还可以参考下面这篇文章:

https://leetcode.com/submissions/detail/153326640/

如果有两个只出现1次的元素怎么办呢?思路是,把数组分成2部分,每部分含有1个落单的数字,

成对的数字也要分在同一个组里,不能一边一个。这样就又回到了原题的模式了。

问题是怎么划分这两个数组呢?

第一步,取整个数组的异或,得到的结果是两个落单元素的异或结果。

第二步,从这个结果中,找出右边开始第一个为1的bit位。这说明这一位两个数字一个是0一个是1,这一位就是两个落单元素的不同点,按照这个特征就可以把两个元素分开,同时还可以保证不会把成对的元素分到两个区里,因为成对的元素这个bit位上的值一定是相同的。

第三步,当然,第二步的分组并不需要实际操作,只需要遍历数组,按照特征分别进行异或去重即可。

在第二步中,用到的一个技巧是:

    对于一个数字X,X&(-X)之后得到的数字,是把X中最右边的1保留下来,其他位全部为0。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值