[LC338] Counting Bits

来源:互联网 发布:新鸳鸯蝴蝶梦 知乎 编辑:程序博客网 时间:2024/06/05 16:40

Total Accepted: 29725
Total Submissions: 52050
Difficulty: Medium

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:
For num = 5 you should return [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.
Hint:

You should make use of what you have produced already.
Divide the numbers in ranges like [2-3], [4-7], [8-15] and so on. And try to generate new range from previous.
Or does the odd/even status of the number help you in calculating the number of 1s?

计算在[0,num]范围内每个数字的二进制形式有多少个1存在,最粗暴的方法是从0开始,每个数字循环其32位,和1做与操作,看有多少个1存在。这种方法简单直接,虽然在形式上还是O(n)复杂度,但在实际操作上无疑是非常慢的,考虑到较小的数字实际上最高有效位仅仅几个,为了这个而循环32位,浪费了许多时间。

这道题的 tag 是 dynamic programming,某种程度上提示了我们很多。

这道题某种程度也很像是一道找规律的题,我们可以发现某种归还规律。

当 num 为0 时,位数为0;

num = 1 时,位数为1;

num = 2 时,位数为1;

num = 3 位数为 2;

可以发现每当过了2的n 次幂以后,之后的位数相当于从0开始重新计数+1(来源于整数次幂带来的1)

因此结果就非常直接

public class Solution {    public int[] countBits(int num) {        int[] dp = new int[num+1];        dp[0] = 0;        if(num == 0){            return dp;        }        dp[1] = 1;        int upper = 2;        for(int i = 2; i <= num; i++){            if(i == upper){                dp[i] = 1;                upper = upper*2;                continue;            }            int res = i - upper/2; // 超过2的 n 次幂以后,循环之前的数列            dp[i] = dp[res]+dp[upper/2];        }        return dp;    }}

Runtime: 3 ms

0 0