[LC338] Counting Bits

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值