位运算chapter1+⅔:与运算‘&’提升---Brian Kernighan算法

Brian Kernighan算法介绍:

两个核心操作:n&(-n)和n&(n-1)

①n&(-n)

n & (-n) 这个操作用来获取一个数 (n) 在二进制表示下最低位的1,和它的位位置。

在二进制系统中,负数通常以补码(two’s complement)的形式存储。一个正整数的补码就是它的反码(每个二进制位取反)加1,对应的算式是-n=~n+1。因此,当你做 n & (-n) 时,实际上你将 n 和 n 的补码进行位与操作。

这个操作的效果是,所有 n 最低位1以上的位都会被设置为0,因为 n 和 -n 在这些位置上数值相反。只有最低位的1会在 n 和 -n 中保持一致(因为n的补码是从最低位的1开始取反的),因此这个位与操作返回的结果就是只有这个位是1其他都是0的数值。

例如,给定数字 n = 10(二进制表示为 1010),n & (-n) 的计算方法如下:

  1. n = 1010
  2. -n = ~(1010 - 1) + 1 = ~(1001) + 1 = 0110 + 1 = 0111 (即负数n的表示)
  3. n & (-n) = 1010 & 0111 = 0010

结果 0010 就是数 10 的二进制表示中最低位1所在的位置。

②n&(n-1)

n & (n - 1) 这个操作的作用是将n二进制表示的最低位的1置为0。

让我们详细看看这个操作是如何工作的:

  1. 二进制表示:每个非负整数 n 都有一个二进制表示,例如,数 13 的二进制表示为 1101。

  2. 减一操作:当我们从一个数 n 减去 1,则 n 的最右边的 1 会变成 0,并且这个 1 右边的所有 0 都变为 1。所以,如果 n = 13 (1101 in binary),那么 n - 1 = 12 (1100 in binary)。

  3. 位与操作:位与操作 (&) 只在两个相应的位都为1的时候才返回1。当你做 n & (n - 1) 时,从 n 中减 1 得到的数字会将 n 中最低位的1变为0(因为那个位在 n 中是1,在 n-1 中变成了0),而所有低于这个位的位都是0(因为在 n 中这些位是0,在 n - 1 中是1,0 AND 1 的结果是0),因此这些位的与操作结果还是0。高于最低位的1的位不会变化,因为在两个数中它们保持不变。

让我们使用13这个数来演示 n & (n - 1) 的具体操作:

  1. n = 1101 (13)
  2. n - 1 = 1100 (12)
  3. n & (n - 1) = (1101) & (1100) = 1100

这个操作将最右边的1变成了0,现在的数值是 12。重复这个过程:

  1. n = 1100 (12)
  2. n - 1 = 1011 (11)
  3. n & (n - 1) = (1100) & (1011) = 1000

又一次,将最右边的1变成了0,现在数值是 8。如果一直重复这个操作,最后将会归0。

实例:

①判断一个数是否是2的幂
class Solution {
public:
	bool ispow2first(int n) {
		return n == (n & -n);
	}
	bool ispow2second(int n) {
		return (n & (n - 1)) == 0;
	}
};

这两种实现分别基于两个核心操作:n&(-n)和n&(n-1)
首先,2的幂的二进制表达式除了最高位1以外其余都是0。
2:10,4:100:128:10000000
第一种实现逻辑是如果一个数的二进制内码取最低位1后仍是它本身,那么这个数就是2的幂
第二种实现逻辑是如果一个数的二进制内码删除最低位1后等于0,那么这个数就是2的幂
测试点:
231. 2 的幂 - 力扣(LeetCode)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值