比特位计数(21-03-03)

给定一个非负整数 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、创建一个数组,这个数组得length是num+1, 因为按题目意思,包含本身
2、要知道每一个数中二进制1得个数,首先不停得操作 i%2 如果余数为1 就是有1
代码

class Solution {
    public int[] countBits(int num) {
        int []arr=new int[num+1];
        for(int i=0;i<num+1;i++){
            int n=0;
            int su=i;
            while(su>0){
                if(su%2==1){
                 n++;
                }
                su /=2;
            }
            arr[i]=n;
       }
       return arr;
    }
}

上面得方法用了20ms,比其他人慢10倍,主要是 % / 运算花费时间,
改进后,使用 x&= (x-1),用位运算会快很多,因为二进制运算直接运行在机器语言上,比较快

  • x&= (x-1) 这个就每次x&(x-1)都会消除一个 1 所以 ones++,比喻如果是x=10
    10&9==>1010 & 1001 = 1000 结果为8这里ones=1,
    8&7==>1000 & 0111 = 0000 结果为8这里ones=2,
    所以10有2个1;
class Solution {
    public int[] countBits(int num) {
        int[] bits = new int[num + 1];
        for (int i = 0; i <= num; i++) {
            bits[i] = countOnes(i);
        }
        return bits;
    }

    public int countOnes(int x) {
        int ones = 0;
        while (x > 0) {
            x &= (x - 1);
            ones++;
        }
        return ones;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容