家喻户晓,lowbit是为了获取一个数的二进制中最低位的1对应的值,比方lowbit(10) = 10,因为10的二进制表白是1010。

lowbit的实现

lowbit有两种实现形式:

  1. 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。
  2. x & -x
    这种算法其实是利用了计算机的补码性质。计算机为了示意正数,将对应的负数二进制全副取反再加一。
    以x=11010000为例,-x=00101111 + 1 = 00110000,能够看到,取反加一后原数最初一个1前面的所有0还是0(因为加法的进位操作),原数最初一个1前的所有1都变成了0,而所有0都变成了1,其实次要外围就是将最初一个1后面的数都翻转,这样再与原数进行或操作,最初一个1后面都会是0,也就是
    11010000 &
    00110000
    后果是00010000。

lowbit的利用

  1. 统计二进制下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。

参考:

  1. https://www.jianshu.com/p/6c3...
  2. https://blog.csdn.net/qq_4172...
  3. https://www.cnblogs.com/fusiw...