LeetCode笔记:338. Counting Bits

本文介绍了一种高效计算0至给定非负整数范围内每个数字二进制表示中1的数量的方法,并提供了一个线性时间复杂度的Java实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

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.

大意:

给出一个非负整数num。对于 0 ≤ i ≤ num 范围的每个数计算它们二进制表示的数中的1的个数,并返回它们组成的数组。

例子:
对 num = 5 你应该返回 [0,1,1,2,1,2]。

进阶:

  • 很容易找到时间复杂度为 O(n*sizeof(integer))的解决方案。但你能不能在线性时间复杂度O(n)中解决呢?
  • 康健复杂度需要是O(n)。
    你能不能像一个boss一样做?不要使用像c++中 __builtin_popcount 一样的内置的函数去做。

思路:

把0~7的二进制表示法的数字列出来,数其中的1的个数,找到一个规律,0对应的数是0,1、2对应的是1个1。往上走只用计算不断除以2一直除到1后,存在余数为1的次数,加上最后的1,就是该数二进制表示法中1的个数。

注意初始化结果数组的时候容量为 num+1,不是 num。

我的做法时间复杂度应该是O(nlogn)。

初始化int型数组后,数组所有元素默认为0,所以对0的判断处理可以略去。

代码(Java):

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

    }
}

他山之石:

public int[] countBits(int num) {
    int[] f = new int[num + 1];
    for (int i=1; i<=num; i++) f[i] = f[i >> 1] + (i & 1);
    return f;
}

这个做法把上面的思想简化了很多,i&1其实就是看最后一位有没有1,也就是取余为1。然后加上 f[i >> 1],这个其实就是当前数字除以2后对应的数字的1的个数,所以可以看出我的做法做了很多无用功,因为没有利用到已经得出的结果,而这个做法的时间复杂度就是O(n)了。


合集:https://github.com/Cloudox/LeetCode-Record
版权所有:http://blog.youkuaiyun.com/cloudox_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值