zoukankan      html  css  js  c++  java
  • 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;
        }
    };
  • 相关阅读:
    无限维
    黎曼流形
    why we need virtual key word
    TOJ 4119 Split Equally
    TOJ 4003 Next Permutation
    TOJ 4002 Palindrome Generator
    TOJ 2749 Absent Substrings
    TOJ 2641 Gene
    TOJ 2861 Octal Fractions
    TOJ 4394 Rebuild Road
  • 原文地址:https://www.cnblogs.com/qq874455953/p/9901068.html
Copyright © 2011-2022 走看看