338、比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
进阶:
- 给出时间复杂度为O(n*sizeof(integer))的解答非常容易。但你可以在线性时间O(n)内用一趟扫描做到吗?
- 要求算法的空间复杂度为O(n)。
- 你能进一步完善解法吗?要求在C++或任何其他语言中不使用任何内置函数(如 C++ 中的 __builtin_popcount)来执行此操作。
题解
1、比较每一个二进制位
- Pop count
- 代码
// java
class Solution {
public int[] countBits(int num) {
int[] res = new int[num+1];
res[0] = 0;
for (int i = 1;i <= num;i++) {
res[i] = getNumberOf1(i);
}
return res;
}
private int getNumberOf1(int i) {
int ans = 0;
int mask = 1;
while(mask <= i) {
if ((i&mask) == mask) {
ans++;
}
mask <<= 1;
}
return ans;
// Pop count
// int count;
// for (count = 0; x != 0; ++count)
// x &= x - 1; //zeroing out the least significant nonzero bit
// return count;
// 作者:LeetCode
// 链接:https://leetcode-cn.com/problems/counting-bits/solution/bi-te-wei-ji-shu-by-leetcode/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
}
}
2、动态规划+最高有效位
- 两个数字二进制表示,相差的最高位(2^m),利用之
- Pop acount P(x) :
- $P(x + b) = P(x) + 1, b = 2^m > x$
- 代码
// Java
class Solution {
public int[] countBits(int num) {
// 返回的结果
int[] ans = new int[num + 1];
// 辅助变量
int i = 0, b = 1;
// 遍历每一位
while (b <= num){
// 处理0~num里面的每一个数字
// i < b 是进位终止,有2 4 8 16 。。。
// i+b <= num 是结束终止
while(i < b && i + b <= num) {
// ans[i]都是已经计算过的解
ans[i + b] = ans[i] + 1;
++i;
}
i = 0;// 重置
b <<= 1;// 左移一位
}
return ans;
}
}
3、动态规划+最低有效位
- 两个数字二进制表示,相差的最低位(x/2 + x%2),利用之
- $P(x) = P(x >> 2) + (x % 2)$
- 代码
// Java
class Solution {
public int[] countBits(int num) {
// 返回的结果
int[] ans = new int[num + 1];
// 循环处理
for (int i = 1;i <= num;i++) {
// i>>1 ==> i/2 i & 1 ==> i%2
ans[i] = ans[i>>1] + i&1;
}
return ans;
}
}
4、动态规划+最后设置位
- 对于x, 其与x-1相差的1的个数用下面的公式:
- $P(x) = P(x & (x - 1)) + 1$
- 代码
// Java
class Solution {
public int[] countBits(int num) {
// 返回的结果
int[] ans = new int[num + 1];
// 循环处理
for (int i = 1;i <= num;i++) {
ans[i] = ans[i & (i - 1)] + 1;
}
return ans;
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com