给定一个非负整数 n ,请计算 0 到 n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
示例 1:
输入: n = 2
输出: [0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10
示例 2:
输入: n = 5
输出: [0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101
思路:
对于每个数进行位运算,对于每一位取模2看余数
class Solution {
public:
vector<int> countBits(int n) {
vector<int> vi;
for(int i=0;i<=n;i++){
int t = i;
int count = 0;
while(t>0){
count += t%2==1?1:0;
t = t>>1;
}
vi.insert(vi.end(),count);
}
return vi;
}
};
另:Brian Kernighan 算法
Brian Kernighan 算法的原理是:对于任意整数 x,令 x=x & (x−1),该运算将 x的二进制表示的最后一个 1变成 0。因此,对 x重复该操作,直到 x 变成 0,则操作次数即为 x的「一比特数」。
int countOnes(int x) {
int ones = 0;
while (x > 0) {
x &= (x - 1);
ones++;
}
return ones;
}
进阶:动态规划
当前x(count = vi[x])=最高位y(count = 1)+余数z(count = vi[z])
对于最高位的判断:i&(i-1)==0
参考代码:
class Solution {
public:
vector<int> countBits(int n) {
vector<int> bits(n + 1);
int highBit = 0;
for (int i = 1; i <= n; i++) {
if ((i & (i - 1)) == 0) {
highBit = i;
}
bits[i] = bits[i - highBit] + 1;
}
return bits;
}
};