基础知识点
位计算判断2的幂
由于一个计算机是二进制存储数据,比如:
12 = 000001100
即 2^0 * 0+ 2^1 * 0+ 2^2 * 1+ 2^3 * 1 = 12;
对于2的幂次方有特点就是二进制中只有一个位为1;即
2^0 = 1 = 00000001;
2^1 = 2 = 00000010;
2^2 = 4 = 00000100;
2^3 = 8 = 00001000;
对于只有一个1的二进制有一个特点
int n; // n为2的幂次
n&(n-1) == 0 //return true;
这是一个判断2的幂次方的快速方法:n & (n - 1) == 0
;
同时运算式:n = n & (n - 1)
可以把n的二进制的最后一个为1 的位置0;
算法分析
利用 Brian Kernighan 算法,可以在一定程度上进一步提升计算速度。Brian Kernighan 算法的原理是:
对于任意整数 x,令x=x & (x−1),该运算将 xx 的二进制表示的最后一个 1 变成 0。因此,对 x 重复该操作,直到 x 变成0,则操作次数即为 x 的「一比特数」。
对于给定的 n,计算从 0 到 n 的每个整数的「一比特数」的时间都不会超过 O(logn),因此总时间复杂度为 O(nlogn)。
实现代码
int countOnes(int x) {
int ones = 0;
while (x != 0) {
x &= (x - 1);
ones++;
}
return ones;
}
vector<int> countBits(int n) {
vector<int> bits(n + 1);
for (int i = 0; i <= n; i++) {
bits[i] = countOnes(i);
}
return bits;
}