方法1:
正整数 i
i&(i-1) 是去掉 i二进制表示序列 从左往右第一个1.所以说i+1也不会发生进位,那么我们只要统计 i&(i-1) 里面1的个数,在加上1,就是 i 的二进制表示中 1的个数。i&(i-1) 的结果比 i小,所以只要将 比 i小的整数的1的个数 存放在数组里面,在计算整数 i中 1的个数的时候,可以用到 前面部分的数组。
------------------------------------------------------------------------
举例说明是去掉从左往右第一个1
7:111
7-1:110
111&110 = 110(去掉7的从左往右第一个1)
6:110
5:101
110&101 = 100(去掉6的从左往右第一个1)
----------------------------------------------------------------------
下面是发现规律:数组从1开始存放,数组的索引就是整数,对应索引的值就是1的个数
0 :A[0] = 0
1 :001 i&(i-1)=000,,A[1] = A[i&(i-1)]+1
2 :010 i&(i-1)=000=0(十进制), i&(i-1) < i,i之前的整数 1的个数已经统计过了,而且i&(i-1) 是去掉i二进制序列从右往左第一个1,所以只要 A[i&(i-1)]+1 = i 的1 的个数
后面类似
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num+1);
for(int i = 1;i<=num;i++){
res[i] = res[i&(i-1)]+1;
}
return res;
}
};
时间复杂度分析:O(k)
方法2:
class Solution {
public:
vector<int> countBits(int num) {
vector<int> res(num+1);
for(int i = 1;i<=num;i++){
res[i] = res[i>>1]+ (i&1);
}
return res;
}
};