关于位运算的骚操作只有你不懂?

位移运算的特性

  1. & (与),两个数都为1相与结果为1,除此之外都为0。

  2. | (或),两个数只要有其中一个为1,结果为1。

  3. ~ (非),这是对单数操作的取反操作,1的非是0,0的非是1。

  4. ^ (异或),两个数不同异或结果为1,相同为0。例如:
    1 ^ 0=1,1 ^ 1=0,0 ^ 0=0。

  5. >> 左移,所有数全部向左移动,这里均指逻辑左移,相当于结果乘2。

  6. << 右移,所有数全部向右移动,这里均值逻辑右移,相当于结果除2。

1、判断奇偶性

奇偶性的判断准则是能否被2整除,在二进制的世界里只要末尾非1即可。根据与的原则可以用以下处理。

                         n & 1 == 1?奇:偶  

2、求一个数2的次方

根据每左移一位相当于乘2的原则,则

    						x*(2^n)=x<<n。

3、交换变量

int a,b;交换a、b不引用中间变量,根据异或的性质,相同的数异或为0,不同的数异或为1,则实现交换只需要 a=ab;b=ab;a=a^b;

相当于a = a ^ a ^ b; b = a ^ a ^ b ^ a; 所以a = b,b = a;

4、假设一个数组中只有一个数出现过1次,其余均出现2次,找出出现一次的这个数

这是leetcode里面的一道题,这里面主要是利用了异或的性质,两个相同的数异或为0,所以只需要整个数组都异或,剩下的就是要找的那个数。

for(int i = 0;i<a.length;i++) x ^= a[i];

这里面也可以找出2个数出现1次,三个数出现1次,可以自行研究,方法类似,稍微拓展了一些。

5、求二进制数中1的个数

这个题也是利用了与的性质,,总的时间复杂度为O(n)。


for(int i = 0;i<<length;i++){

        num = num >> i;

        if (num & 1 != 0){

            count++;

}

}

6、正整数n,找出大于n,并且最接近2的次方

看过jdk中hashmap源码的人一定知道,扩容的时候用的就是这个方法,md太精妙了。解释一下思路:就是要找到最高位是1,然后将最高位左移一位,最开始将最高位和次位变成1,


int n = cap - 1;    
    n |= n >>> 1;

然后由2为变成4位,4位变成8位,8位变成16位,16位变成32位,最后加个1就可以将原来的最高位左移1位,低位全部变成0,只用了5次运算,时间复杂度直接是常数。


static final int MAXIMUM_CAPACITY = 1 << 30;//将最高位致1,除符号位外
static final int tableSizeFor(int cap) {
    int n = cap - 1;    
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

关注公众号:计算机基础爱好者

致力于更多干货内容输出

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值