比特位计数-记忆化搜索与动态规划

题目描述

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)来执行此操作。

题解

暴力解法

暴力解法很简单,每次逐位扫描,时间复杂度为O(n*sizeof(integer))。

记忆化搜索与动态规划

从0到num统计的过程中,我们会发现:

假设当前的数是100101,很明显去掉最高位的1,数00101的1的位数前面已经统计过了,1得个数只需要再加1即可,类似递归的思想。

因此我们有了以下思路:

  假设当前的数是j,

  一定存在i,使得     2^i  <= j <  2^(i+1)

那么bitsArr[j] = bitArr[j-2^i] + 1。

代码:

 1 class Solution {
 2     public int[] countBits(int num) {
 3         int[] bitsArr = new int[num+1];
 4         bitsArr[0] = 0;
 5         if(num>=1){
 6             for(int i=0;(int)(Math.pow(2,i))<=num;i++){
 7                 bitsArr[(int)(Math.pow(2,i))]=1;
 8                 for(int j=(int)(Math.pow(2,i))+1;j<(int)(Math.pow(2,i+1))&&j<=num;j++){
 9                     bitsArr[j]=bitsArr[j-(int)(Math.pow(2,i))]+1;
10                 }
11             }
12         }
13         return bitsArr;
14     }
15 }

优化

上述解法较多调用了幂运算和int转换,效率较低。下面采用位运算优化。

 使用i&(i-1)==0来判断i是否是2的整数幂。
代码:
 1 class Solution {
 2     public int[] countBits(int num) {
 3         int[] bitsArr = new int[num+1];
 4         bitsArr[0] = 0;
 5         int powOf2 = 0;//存放2的整数幂
 6         for(int i=1;i<=num;i++){
 7             if( (i&(i-1))==0 ){//如果i是2的整数幂
 8                 powOf2 = i;
 9                 bitsArr[i] = 1;
10             }else{
11                 bitsArr[i] = bitsArr[i-powOf2] + 1; 
12             }
13         }
14         return bitsArr;
15     }
16 }

另解-最低位

上述解法其实是去掉最高位,将低位求解转化为已经求得的数,其实还可以去掉右移一位去掉最低位,转化为已经求得的数,再根据去掉的那一位是0还是1来判断是否额外加1。

代码:

 1 class Solution {
 2     public int[] countBits(int num) {
 3         int[] bitsArr = new int[num+1];
 4         bitsArr[0] = 0;
 5         for(int i=1;i<=num;i++){
 6             bitsArr[i] = bitsArr[i>>1] + (i&1);
 7         }
 8         return bitsArr;
 9     }
10 }

 

posted @ 2021-03-03 11:10  HickeyZhang  阅读(115)  评论(0)    收藏  举报