位运算的奇巧淫技(一)

本文主要列举与、或、异或、等位运算符的一些奇巧淫技,顺便把用到这些技巧的算法题列出来讲解。

异或

// 异或底层原理,相同为0,不相同为1.
1 ^ 1 = 0
1 ^ 0 = 1
// 所以有任意数异或0为本身,相同两个数异或为0.
a ^ 0 = a
a ^ a = 0
// 根据上面的公式得
a ^ a ^ b = b

下面看道用到此技巧的算法题目。

在这里插入图片描述

1、任何数和 0 做异或运算,结果仍然是原来的数,即 a ^ 0 = a。
2、任何数和其自身做异或运算,结果是 0,即 a ^ a = 0。
3、异或运算满足交换律和结合律,即 a ^ b ^ a = b ^ a ^ a = b ^ (a ^ a) = b ^ 0 = b

思路:对数组全部元素进行异或操作,出现次数为偶数的都相互抵消为0,因为只有一个元素出现一次,其他元素都出现两次,也就是相当于 0 ^ a = a,最后运算结果就是只出现一次的元素。

代码如下:

class Solution {
    public int singleNumber(int[] nums) {
        int a = 0;
        for (int num : nums) {
            a ^= num;
        }
        return a;
    }
}

进阶版:给定一个数组长度为K,其中一个元素重复两次,其余元素只出现一次,数组元素范围[1,K],找到重复两次的这个元素;这道题就留给各位解答吧。

n & (n-1)

这个公式就是布赖恩·克尼根算法,目的就是消除n二进制表示中最后的一个1。
布赖恩·克尼根算法
下面看几道用到此技巧的算法题目。

汉明距离

思路:对于两个数对应二进制不同的位置的数目我们可以先对两个数进行异或 x ^ y = xor,之后再统计xor二进制位1的个数。

代码如下:

//思路1
class Solution {
     public int hammingDistance(int x, int y) {
        //清除相同进制位;
        x ^= y;
        //获取 1 的个数;
        int count = 0;
        while (x!=0){
            x&=(x-1);
            count++;
        }
        return count;
    }
}
//思路2,使用java内置函数,统计1的个数。
class Solution {
     public int hammingDistance(int x, int y) {
        return Integer.bitCount(x ^ y);
    }
}

2的幂

思路:只要是2的幂,那么这个数它的二进制位只有一个1。

// 1 = 0b 0001
// 2 = 0b 0010
// 4 = 0b 0100
class Solution {
     public boolean isPowerOfTwo(int n) {
         if(n<=0){
             return false;
         }
        return (n & (n-1))==0;
    }
}

4的幂

思路:只要是4的幂,那么这个数它的二进制位只有一个1,不同2的幂的是,它只能是奇数位为1。
我们可以将 n & 0x55555555,如果结果不为0,则n就为4的幂。

//  1 = 0b 0000 0001
//  4 = 0b 0000 0100
// 16 = 0b 0001 0000
class Solution {
    public boolean isPowerOfFour(int num) {
         if(num <= 0 || (num & (num-1)) != 0){
             return false;
         }
        return (num & 0x55555555) != 0;
    }
}

为什么要 n & 0x55555555?其实很简单

/*  5 = 0b 0101
* 2进制转16进制,2进制每4位等于16进制1位。
* 0x5555 5555 = 0b 0101 ... 0101 (重复8次)
* 所以如果是要偶数位,我们可以先设 n = 0b 1010,n = 10,x = 0x AAAA AAAA 

以上便是一些简单的位运算技巧,下期继续更新位运算更多高级解题方法。喜欢的点个订阅吧!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值