数组中数字出现的次数(位运算)

84 篇文章 3 订阅
75 篇文章 0 订阅

在这里插入图片描述
要求必须是O(1)空间复杂度,那么必然不能使用哈希表或者桶这样的集合:
只能考虑用位运算解决:
看代码之前我们一定要明白异或运算的几个性质:a^ b ^ c = a ^ c ^b,a ^ b=b ^ a,即满足交换律和结合律,a ^ a=0,a ^ 0=a;
那么数组中所有元素异或的结果就是那两个只出现了一次的数异或的结果,接着只需要考虑将这个两个数分开即可:

那么我们需要明白的是这个结果产生的二进制数是异或的结果,就意味着从右往左数结果rec出现的第一个1就代表了两个数从右往左在这个位置不一样,一个为0,一个为1,用while((rec&mask)==0){ mask<<=1; }找到这个位置mask。

那么在回到数组每一个数去跟mask相&,分成两组数,那么两个需要的数分别在两个数组中,因为你他们在mask位置,一个为1,一个为0,而mask除了这个位置为1,其余全为0,每组数都去异或一下就得到了两个要求的数,记住a ^ a=0,

class Solution {
    public int[] singleNumbers(int[] nums) {
     int idx=0;
     int rec=0;
     for(int num:nums){
      rec^=num;
     }
     int mask=1;
     while((rec&mask)==0){
      mask<<=1;
     }
     int a=0,b=0;
     for(int nu:nums){
         if((nu&mask)==0)a^=nu;
         else b^=nu;
     }
   
    return new int[]{a,b};
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值