题目描述
思路1:
- 写一个返回2进制中1数量的函数countOne
- 遍历0到num,对每一个数使用countOne,并将结果保存到res中返回
var countBits = function (num) {let res = new Array(num + 1).fill(0);for (let i = 0; i <= num; i++) {res[i] = countOne(i.toString(2));}return res;
};const countOne = num => {let res = 0;for (let i = 0; i < num.length; i++) {if (num[i] == 1) {res++;}}return res;
}
思路2:
- 上面求1的个数的速率可以提升,可以考虑采用位运算来求
var countBits = function (num) {let res = new Array(num + 1).fill(0);for (let i = 0; i <= num; i++) {res[i] = countOne(i);}return res;
};const countOne = num => {let res = 0;while (num > 0) {res++;num = num & (num - 1);}return res;
}
思路3:
找到后面数与前面数的联系,利用缓存进一步加速
- 对于十进制10来说,其对应的二进制为"1010",其1的位数dp[10]为十进制2中1的位数 + 1,其对应公式如下:
dp[10] = dp[2] + 1;
- 10与2之间其实只差一个十进制8(“1000”)
- 同理十进制13(“1101”)其1的个数可以由公式 dp[13] = dp[5] + 1 求出
十进制5的二进制对应"101"
- 因此可以得到递推关系式, dp[i] = dp[i - highBit] + 1;
其中 highBit是不超过i的2的最大整数次幂
算法如下:
var countBits = function (num) {let dp = new Array(num + 1).fill(0);let highBit = 0;for (let i = 1; i <= num; i++) {if ((i & (i - 1)) == 0) {highBit = i;}dp[i] = dp[i - highBit] + 1;}return dp;
};