力扣解题思路:位运算系列

交换两个整数


思路:给定a,b用位运算交换两个数的值:

a = a ^ b;
b = a ^ b;//b = a ^ b ^ b (这里a,b是初始a,b)
a = a ^ b;//a = a ^ b ^ a ^ b ^ b (这里a,b是初始a,b)

461.汉明距离


思路:对两个数进行异或操作,位级表示不同的那一位为 1,统计有多少个 1 即可。不断的判断最低位是否为1,为一则计数加一,然后将该数右移一位:

public int hammingDistance(int x, int y) {
   
    int z = x ^ y;
    int cnt = 0;
    while(z != 0) {
   
        if ((z & 1) == 1) cnt++;
        z = z >> 1;
    }
    return cnt;
}

当然,还有一种比较简单的方法,z&(z-1)操作可以每次消去z中的一个1,所有1消去完全后z就等于0:

    while (z != 0) {
   
        z &= (z - 1);
        cnt++;
    }

另外,还可以调用相应的API:

Integer.bitCount(x ^ y)

这一题和牛客:二进制中1的个数相似,这里题目中负数用补码表示。
补码是这样的:

下面求-9 补码:先减一:0000 1001 - 1 = 0000 1000;
再取反:1111 0111。
所以有:-9 补码 = 1111 0111

有人可能会疑惑负数怎么办,其实z &= (z - 1)中减一就相当于把原来的数最右边的一个1变为0,再与原数进行与操作,就能得到这个位置左边保持不变,右边(包括它自己)变为0。

136.唯一数字


思路:找出数组中唯一一个不重复的元素。两个相同的数异或的结果为 0,对所有数进行异或操作,最后的结果就是单独出现的那个数。

public int singleNumber(int[] nums) {
   
    int ret = 0;
    for (int n : nums) ret = ret ^ n;
    return ret;
}

476. 数字的补数


思路:给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

除了Map我并没有想出别的方法,因为我实在不擅长位运算。。。不过我在评论里找到了一种更容易理解的方法,我觉得太巧妙了!!
每个数想象成32位的二进制,对于每一位的二进制的1和0累加起来必然是3N或者3N+1, 为3N代表目标值在这一位没贡献,3N+1代表目标值在这一位有贡献(=1),然后将所有有贡献的位|起来就是结果。这样做的好处是如果题目改成K个一样,只需要把代码改成cnt%k,很通用。

public int singleNumber(int[] nums) {
   
    int ret = 0;
    for (int i = 0; i < 32; i++) {
   
        int mask = 1 << i;
        int cnt = 0;
        for (int j = 0; j < nums.length; j++) {
   
            if ((nums[j] & mask) != 0) {
   
                cnt++;
            }
        }
        if (cnt % 3 != 0) {
   
            ret |= mask;
        }
    }
    return ret;
}

268.缺失数字


思路:数组元素在 0-n 之间,但是有一个数是缺失的,要求找到这个缺失的数。原理和上一题类似,可以肯定数组中是存在 0-n 的数的(除了那个缺失的),所以我们将数组中所有数和 0-n 异或,相同的数就抵消,最后只剩下那个缺失的数:

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

剑指 Offer 56 - I. 数组中数字出现的次数

思路:

在这里插入图片描述

    // 假设结果数为A B
    public int[] singleNumbers(int[] nums) {
   
        int x = 0; // 用于记录 A B 的异或结果
        
        /** 得到A^B的
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值