• 338. Counting Bits题目详解


    题目详情

    Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1’s in their binary representation and return them as an array.

    Example 1:

    Input: 2
    Output: [0,1,1]

    Example 2:

    Input: 5
    Output: [0,1,1,2,1,2]
    

    Follow up:

    • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
    • Space complexity should be O(n).
    • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.

    分析

    解法1 —— 直接求解

    当然最简单的做法就是遍历1-n,然后每个数字直接求其1的数字,这样复杂度变成了O(nlogn)
    这里就不给出具体代码了

    解法2 —— 动态规划问题

    我们可以把求某个数的1的个数,写出一个递推式
    定义re 为返回的数组, 则re[i] 就表示 i的二进制表示中的1的个数,我们把i的二进制表示分成两段,一段为前n - 1位, 另一段为 最右边一位。
    所以得到 re[i] = 前n-1位中的1的个数 + i%2
    而 前n-1位中1的个数可以用re数组的一个元素来表示, 也就是re[i >> 1]

    所以得到递归式子

    re[i] = re[i>>1] + i%2;

    然后循环 把re的所有项都得到。解法1之所以复杂度高是因为每次算1的个数的时候重复计算了前面的1的个数, 而动态规划里把前面数字的1的个数都记录下来,避免了重复计算, 但是这也要求需要一个数组来存储结果, 这是通过牺牲空间来换取时间的一种策略

    代码如下:

    class Solution {
    public:
        vector<int> countBits(int num) {
            vector <int> re(num+1, 0);
    
            for (int i = 0; i <= num; i++) {
                re[i] = re[i>>1] + i%2;
    
            }
    
            return re;        
        }
    };

    解法3

    这是最快的一种解法

    /* 
            Dynamic programming 
            Reoccurence relation:
                    dp[i] = dp[i & (i - 1)]] + 1 where i & (i - 1) erases right most bit
                    i & -i gives rightmost bit => i - (i & -i) erases rightmost bit
            O(n)
    */
    
    class Solution {
    public:
        vector<int> countBits(int num) {
            vector<int> dp(num + 1, 0);
    
            for (int i = 1; i < num + 1; ++i) {
                dp[i] = dp[i & (i - 1)] + 1;
            }
    
            return dp;
        }
    };
  • 相关阅读:
    Shell编程(/bin/sh和/bin/bash) 迎客
    Ubuntu命令大全 迎客
    一位软件工程师的6年总结(转) 迎客
    Ubuntu中常见特殊符号 迎客
    Nginx 简介 迎客
    IO流File对象功能删除指定目录中的空白目录
    五步让你成为专家级程序员
    关于eclipse 中文注释时中文字体太小的问题解决
    实现一个小小的动态时钟
    深入解析HashMap、HashTable
  • 原文地址:https://www.cnblogs.com/qq874455953/p/9901068.html
Copyright © 2020-2023  润新知