Java位运算

n&1:与操作,判断 n 二进制最右一位是否为 1 。

// 若等于1,表示最右一位是1;
// 否则是0.
if ((n & 1) == 1) {
    ...
}

n&1常用来判断n是奇数还是偶数。

if (n & 1) == 1):
    n为奇数
if (n & 1) == 0):
    n为偶数 

n>>1:移位操作,删除n二进制的最右一位。

n = n>>1;
// 简写如下
n >>= 1;

n&(n-1)为去除整数二进制的最后一个1。

public class Test {
    public static void main(String[] args) {
        // 5的二进制表示为:101
        // 去掉二进制最后一个1,则为:100
        // 转换成10进制为:4
        System.out.println(5&(5-1)); // 4
        // 1010
        System.out.println(10&(10-1)); // 8
        // 1001
        System.out.println(9&(9-1)); // 8
    }
}

一.n&(n-1)的原理和应用

1.原理

在“力扣”中第一道题目就是求一个32位二进制数串中1的个数,在评论区看到这种方法求解,原理附下:

对于一个二进制数(此处设定长度为8位,任何长度同理)n,举例:n=xxxxxxx1,n-1=xxxxxxx0,n和n-1进行&运算,结果为n&(n-1)=xxxxxxx0,由此可见,在n和n-1进行&运算 之后,将n中最末位的1转化为0。再来看一个例子,假如n=xxxx1000,n-1=xxxx0111,n和n-1进行&运算,结果为n&(n-1)=xxxx0000。总结:在一个二进制数串中,只要有1存在,不论1的位置在哪里,进行n&(n-1)的运算之后,总能将最末位的1化为0。

2.应用

了解并掌握以上原理之后,就可以来做这道统计二进制数串中1的个数的题目啦。先上代码:

public class Solution {

public int hammingWeight(int n) {

int ret = 0;

while (n != 0) {

n &= n - 1;

ret++;

}

return ret;

}

}

透过代码,可以看到,在while循环里,当二进制数串n不等于0(即有1存在)时候,对其进行n&(n-1)运算,并在循环外定义一个初始值为0的整数ret。循环体中,每进行一次&运算,计数值ret就加1,这样,当n=0时(即n中的所有1都被0取代),不再进行&运算,同时返回计数值ret,此值就代表n中1的个数。

二.n&(1<<i)的原理和应用

1.原理

首先来明确1<<i的意义,1<<i代表将1左移i位,举例:当i=3时,即为1<<3,结果为(000)1->1000(对于任意一个非0二进制数,我们都可以假定它前边有无数个0,此处1就可以写为0001)。简言之,就是i的值为多少,从右向左计数,第i位的值就为1,其余值为0。由于1左移之后,只有第i位(从右往左计数)是1,其余为都是0,与另一个二进制数n进行&运算,得到的结果可以用来表示n的第i位(从右向左计数)为1还是为0。

2.应用

public class Solution {

public int hammingWeight(int n) {

int ret = 0;

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

if ((n & (1 << i)) != 0) {

ret++;

}

}

return ret;

}

}

透过代码,可以看到,i从0到31(此处的二进制数串位数为32,其他的即为数串长度减1),每一位都进行按位&运算,如果运算结果不等于0,即代表此位为1,计数值ret从0开始计数,每次&运算结果不为0,ret值就加1。当n的所有位置都与1<<i进行&运算之后,结束循环,返回ret值.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值