在数组中找到只出现1次的数字(位运算)

前置知识

异或运算

  • 将2个数的二进制位按位运算,相同的结果为0,不同结果为1.

异或运算性质

  • 任何数和0异或结果为任何数
  • 任何数和自己异或结果为0
  • 异或运算满足交换律

只出现一次的数字(1)

数组中只有一个数字出现一次,其他数字均出现两次。
利用异或,两个相同的数异或为0,任何数与0异或为自己,将这组数字全员异或,得到的结果为出现一次的数字。

class Solution {
    public int[] singleNumbers(int[] nums) {
        int ret = 0;
        for(int i=0; i<nums.length; i++){
            ret = ret^nums[i];
        }
        return ret;
    }
}

只出现一次的数字(2)

较上题来说,难度增加,这组数字有两个出现次数为1的数字。
这次还能直接套用上题的方法吗?
可以是可以,不过还要制造这个机会。
如果单纯的按照全员异或的方式一遍得出的结果是两个出现一次的数字异或的结果。显然结果是不对的。
如果能将这组数分成两组,且刚好一组有一个出现一次的数字,在这两组上分别全员异或一次,就可得到答案。
如何分组?
可以从这组数全员异或的结果下手。
因为这两个数字不同且出现次数均为1,则他们异或的结果中肯定有一位是1。
这个1就代表他们这位是不同的。而二进制数的一位只有两种结果,1/0。
利用这个条件,将此位为1的数分在一组,为0的数分在一组。

class Solution {
    public int[] singleNumbers(int[] nums) {
        int ret = 0;
        for(int i=0; i<nums.length; i++){
            ret = ret^nums[i];
        }
        int tmp = ret & (-ret);  
        ret = 0;
        int ret1=0;
        for(int i=0; i<nums.length; i++){
            if((nums[i]&tmp) == 0){
                ret = ret^nums[i];
            }else{
                ret1 = ret1^nums[i];
            }
        }
        int[] arr = {ret1,ret};
        return arr;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值