比特位计数(力扣第338题)
338.比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
分析:
第一种方法
暴力法:遍历0~num范围的所有数字,然后逐个统计其中1的个数
public int[] countBits(int num) {
int n = num + 1;
int[] res = new int[n];
if (num == 0){
return res;
}
for (int i = 1; i < n; i++) {
int count = 0;
int curNum = i;
while (curNum != 0){
int temp = curNum & 1;
if (temp == 1){
count++;
}
curNum >>= 1;
}
res[i] = count;
}
return res;
}
可以使用Java的内置函数改进一下:
public int[] countBits2(int num) {
int n = num + 1;
int[] res = new int[n];
if (num == 0){
return res;
}
/*
static int Integer.bitCount(n); 统计n的二进制数中1的数量
*/
for (int i = 1; i < n; i++) {
res[i] = Integer.bitCount(i);
}
return res;
}
第二种方法:动态规划
1 001
2 010
3 011
4 100
5 101
6 110
7 111
寻找状态转移函数,求i的含有1的个数,可以通过之前已经求出的结果来求,那么需要先找出与其有关的小于i的数,可知i&(i-1)表示消除i中最右边的那个1,那么一定小于i。
比如 2&1=0,3&2=2,4&3=0,5&4=4,6&5=4,7&6=6;
而2中1的个数是1,3中1的个数是2,4中1的个数是1,5中1的个数是2,6中1的个数是2,7中1的个数是3;
所以根据规律,状态转移函数为 f(i) = f(i&(i-1)) + 1
public int[] countBits(int num) {
int[] ret = new int[num + 1];
for(int i = 1; i <= num; i++){
ret[i] = ret[i&(i-1)] + 1;
}
return ret;
}
参考:https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 位运算.md#11-实现整数的加法