本文已参与「新人创作礼」活动,一起开启掘金创作之路。
位运算 n & (n-1)、Leetcode231、面试题 05.06
作用
n & (n-1)
作用:将最低位的1
改为0
。
举例
6 110 //原始数
& 5 101
--------
4 100 //6 最低位 1 改为 0
& 3 011
--------
0 000 //4 最低位 1 改为 0
应用
判断一个正整数是否为2的幂
如果(n & (n-1)) == 0
则这个正整数为2
的幂。
解释
2
的幂的二进制特点:有且只有一个1
。
如果一个正整数二进制最低位1
改为0
后,没有其他的1
了,那么这个数是2的幂。
求一个数二进制中1的个数
while(n != 0) {
count++;
n &= (n-1);
}
计算N!的质因数2的个数
N!
的质因数2
的个数公式:[N / 2] + [N / 4] + [N / 8] + ...
解释
[N / 2]
在不大于N
的数中,是2
的倍数的有[N / 2]
个,各贡献一个2
。
[N / 4]
在不大于N
的数中,是4
的倍数的有[N / 4]
个,各贡献一个2
,虽然4
的倍数可以贡献2
个2
,但是在[N / 2]
中已经贡献了一个,所以这里只贡献一个。
...以此类推
举例求解
N=21(10101)
[N / 2] + [N / 4] + [N / 8] + ...
可以分解为[(16 + 4 + 1) / 2] + [(16 + 4 + 1) / 4] + ...
可以得出只需求[10000/2]+...``[00100/2]+...``[00001/2]+...
即可
求[10000/2]+...
[10000 / 2] 01000
[10000 / 4] 00100
[10000 / 8] 00010
[10000 / 16] 00001
[10000 / 2] + [10000 / 4] + [10000 / 8] + [10000 / 16] = 01111 = 10000 - 1
同理可得其他位
[00100/2]+... = 00011 = 00100 - 1
[00001/2] = 00000 = 00001 - 1
可得
(10101)!的质因数2的个数为10000 - 1 + 00100 - 1 + 00001 - 1 = 10101 - 3(二进制表示中1的个数)
由此推出
N!
的质因数2
的个数为N - (N二进制中1的个数)
Leetcode 231 2的幂
求一个数是否为2的幂。很简单,不再赘述。
public boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
return (n&(n-1)) == 0;
}
面试题 05.06. 整数转换
求从A数转成B数,需要改变二进制多少位。
思路
求A和B异或后二进制中1的个数。
代码
public int convertInteger(int A, int B) {
int diff = A ^ B;
int ans = 0;
while (diff != 0) {
ans++;
diff &= (diff-1);
}
return ans;
}