家喻户晓,lowbit是为了获取一个数的二进制中最低位的1对应的值,比方lowbit(10) = 10,因为10的二进制表白是1010。
lowbit的实现
lowbit有两种实现形式:
- x & (x ^ (x - 1))
以二进制数x = 11110000为例,x - 1=11101111,容易发现,其实就是将x的最初一个1变为0,再将前面的0都变成1,这样以来,再与x做异或:
11110000 ^
11101111
后果是00011111。也就是把原数x最初一个1以及前面的 0都变成1,把最初一个1后面的1都变成0。既然后面都是零了,那么只有和原数x做和的操作,即可将异或的后果最初一个1前面的1都变成0,也就是
11110000 &
00011111
失去00010000,这样就优雅得失去了最初一个1示意的数,也就是原数x的最大的能够整除的数。这里x的十进制是240,lowbit的后果是16=2^4。 - x & -x
这种算法其实是利用了计算机的补码性质。计算机为了示意正数,将对应的负数二进制全副取反再加一。
以x=11010000为例,-x=00101111 + 1 = 00110000,能够看到,取反加一后原数最初一个1前面的所有0还是0(因为加法的进位操作),原数最初一个1前的所有1都变成了0,而所有0都变成了1,其实次要外围就是将最初一个1后面的数都翻转,这样再与原数进行或操作,最初一个1后面都会是0,也就是
11010000 &
00110000
后果是00010000。
lowbit的利用
- 统计二进制下1的个数
先用原数计算出lowbit(x),而后用原数减去这个数,再一直lowbit。
int ans = 0;while(x > 0){ x -= x & -x; ans++;}
这也是树状数组的实现原理。
基于这个操作咱们能够将合成出一个整数能够由哪些的2的幂相加形成。比方11110000也就是240=2^4+2^5+2^6+2^7。
参考:
- https://www.jianshu.com/p/6c3...
- https://blog.csdn.net/qq_4172...
- https://www.cnblogs.com/fusiw...