【LeetCode】338、比特位计数

一、题目信息

cpp 复制代码
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
不要使用内置函数来解决(例如,C++ 中的 __builtin_popcount)。

示例 1:
输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:
输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

提示:
0 <= n <= 105
进阶:
很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?

二、题解1:朴素解法

1、解题思路:二进制转换法

  • 题目要求计算一个十进制整数的二进制形式中1的数字个数

  • 使用for循环遍历每个数字,然后对遍历到的每个数字进行二进制转换,将十进制转换成对应二进制

  • 在转换的过程中,记录数字1个个数

2、图解

3、代码实现

cpp 复制代码
vector<int> countBits(int n)
{
    vector<int> res(n + 1, 0);

    string binaryStr = ""; // 数字i对应的二进制结果值

    for (int i = 0; i <= n; i++)
    {
        int num = i;
        binaryStr = "";
        while (num != 0)
        {
            // 十进制数字num转换成二进制
            int remainder = num % 2; // 取余数
            int business = num / 2;  // 商

            if (remainder == 1)
            {
                res[i]++;
            }
            num = business;
            binaryStr = to_string(remainder) + binaryStr;
        }
        std::cout << i << " -- " << binaryStr << std::endl;
    }

    return res;
}

4、时间复杂度

  • NlogN ,因为遍历需要计算n次,对每个数字i进行二进制转换需要logN次,结果相乘

三、题解2:位运算&解法

1、解题思路

  • 通过位运算符&,求i&(i-1)的结果值,会将数字i的二进制最右侧的数字1消除掉

  • 这样不断重复这个操作,将所有二进制形式的1消除掉,记录循环的次数就是对应二进制中1的个数

2、图解

3、代码实现

cpp 复制代码
vector<int> countBits(int n)
{
    vector<int> res(n + 1, 0);

    for (int i = 0; i <= n; i++)
    {
        int num = i;
        while (num != 0)
        {
            num = num & (num - 1);
            res[i]++;
        }
    }

    return res;
}

4、时间复杂度

  • NlogN ,每个数字i的二进制1个数为logn的个数,要找出所有1的个数

四、题解3:位移解法

1、解题思路

  • 十进制数字i,要求他的一半大小,只需要将他的二进制形式往右边位移一位

  • 如果这个数字i是偶数的话,那他二进制最右侧的数字是0,i的二进制中1的数字个数,和i/2的二进制中1的数字个数相同。

  • 如果数字i是奇数的话, 对应二进制最右侧的数字肯定是1,那i的二进制往右位移一位后,得到i/2的二进制1的个数比i的二进制1的个数少1.

  • 可以通过这个规律来求解i的二进制中1的个数的值。

2、图解

3、代码实现

cpp 复制代码
vector<int> countBits(int n)
{
    vector<int> res(n + 1, 0);

    for (int i = 1; i <= n; i++)
    {
        res[i] = res[i / 2] + (i & 1);
    }

    return res;
}

4、时间复杂度

  • O(N),动态规划解法,首先要找数字i与i/2的规律,再根据他们的关系来一步步求解
相关推荐
Gigavision1 小时前
DEAP数据集 2026最新Transformer算法 DEAP 数据集 下载
深度学习·算法·transformer
夜之眷属1 小时前
PriorityQueue:for-each 遍历和 poll 取出,顺序一样吗?
java·服务器·数据结构·后端·算法
‎ദ്ദിᵔ.˛.ᵔ₎1 小时前
c++11:fuction包装器
开发语言·c++
地平线开发者2 小时前
不是线程越多越快:用 hrt_model_exec 在 征程6M 上给 YOLOv5x 建立性能基线
算法
霍霍的袁2 小时前
【C++】哈希表实现指南:从原理到开放定址法、链地址法的实现
c++·学习·哈希算法·散列表·visual studio
姜鱼问生2 小时前
fail2ban 实战:从默认配置到生产可用
后端·算法·架构
垆边人似月.2 小时前
华为题:全排列
算法·深度优先·图论
杜 硕3 小时前
快速排序详解01
数据结构·算法·排序算法
Matlab程序猿3 小时前
【MATLAB源码-第459期】基于matlab的D-H模型与阻尼最小二乘逆运动学的六自由度机械臂五次轨迹规划及动力学前馈PD控制仿真。
人工智能·算法·matlab·d-h建模·六自由度串联机械臂
信奥卷王3 小时前
[GESP202606 六级] 满二叉树
数据结构·算法