x & (x-1) 和 x & (-x)
x & (x-1)
x 的 二进制显示是 (1000……1000)2
则(x-1) 的二进制显示就是把从右往左数的第一个1变成0,后面都变成1 : (1000……0111)2
x&(x-1) 相当于把 x 的最后一位1去掉
1.判断x是否是2的n次方
假如x是2的n次方,则x可以表示为(1000……0000)2, 对应的 x-1 表示为 (0111……1111)2
此时 x&(x-1) = 0.
于是乎 x&(x-1) = 0
代表 x 是 2 的 n 次方,或 x 能被 2 整除
2.统计x的二进制表示中1的个数
每执行一次x&(x-1), x中就少了一个1
int func(x)
{
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
}
3.统计0<=i<=nums范围内的二进制数的1的个数
Leetcode338. 比特位计数
i & (i - 1)可以去掉i最右边的一个1(如果有),因此 i & (i - 1)是比 i 小的,而且i & (i - 1)的1的个数已经在前面算过了,所以i的1的个数就是 i & (i - 1)的1的个数加上1
class Solution {
public:
vector<int> countBits(int num) {
vector<int> ans(num + 1, 0);
for(int i = 1; i <= num; ++i){
ans[i] = ans[i & (i-1)] + 1;
}
return ans;
}
};
4.只遍历一个数二进制位为1的部分
class Solution {
public:
int hammingDistance(int x, int y) {
int ans = 0;
int s = x ^ y;
while (s) {
ans++;
s &= s - 1;
}
return ans;
}
};
x&(-x)
这个操作又称 lowbit, 在树状数组里会用到
lowbit(x)=2^p, P是指将x转化为二进制之后从右往左数第一个一的位置。