[力扣每日一题]338.比特位计数
题目详情
给定一个非负整数num,对于0<=i<=num范围中的每一个数字i,计算其二进制书中的1的数目并将它们作为数组返回
进阶
1.争取在线性时间O(n)内用一趟扫描做到;
2.要求算法的空间复杂度为O(n);
3.不使用任何内置函数
1.暴力解法
本题可以看做191题的进阶,暴力解法是基于191中的第二种解法
public class LCode338 {
public static void main(String[] args) {
int num = 5;
System.out.println(Arrays.toString(countBits(num)));
}
private static int[] countBits(int num) {
int[] result = new int[num + 1];
for (int i = 0; i <= num; i++) {
result[i] = countOne(i);
}
return result;
}
private static int countOne(int num) {
int result = 0;
while (num != 0) {
num = num & (num - 1);
result++;
}
return result;
}
}
2.(官方题解)动态规划–最高有效位
首先,用【一比特数】表示二进制中的1的个数,用bits[i]来表示,当计算i的一比特数时:
- 找到k,使bits[i] = bits[k] + 1;
- 对于正整数i,如果可以知道最大正整数j,使得j <= i且j是2的整数次幂,则有bits[i] = bits[i - j] + 1(j最高位为1,其余位为0),其中j称为i的最高有效位,用highBit表示;
- 对于正整数j,当且仅当j&(j - 1) = 0时,j是2的整数次幂;
- 易得bits[0] = 0,故具体的代码思路为:
- 当i & (i - 1) = 0时,说明i为2的整数次幂,此时令highBit=i(更新当前的最高有效位);
- 从小到大遍历每个数,则有bits[i] = bits[i - highBit] + 1
public class LCode338 {
public static void main(String[] args) {
int num = 5;
System.out.println(Arrays.toString(countBits(num)));
}
public static int[] countBits(int num) {
int[] bits = new int[num + 1];
int highBit = 0;
for (int i = 1; i <= num; i++) {
if ((i & (i - 1)) == 0) {
highBit = i;
}
bits[i] = bits[i - highBit] + 1;
}
return bits;
}
}
官方牛逼