【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的规律,再根据他们的关系来一步步求解
相关推荐
郝学胜-神的一滴27 分钟前
游戏设计:原型与开发 19:U3D工位布置与性格说明书
人工智能·算法·unity·unreal engine·游戏策划·游戏设计
東隅已逝,桑榆非晚30 分钟前
红黑树:从概念到实现
数据结构·c++·笔记·学习
艾莉丝努力练剑1 小时前
【AI大模型接入SDK】ChatServer接口测试
网络·c++·人工智能·学习·ai·大模型·sdk
D e re k ZH1 小时前
C++ 模板与泛型编程进阶(No 2)
开发语言·c++
hahaha60161 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
文丑颜不良啊1 小时前
LeetCode1541~1560题目解析
java·leetcode
YSL0701242 小时前
一文通关-----树和二叉树
数据结构·算法
青少儿编程课堂2 小时前
蓝桥杯青少组图形化+信息素养+电子学会Scratch考级:校园口算闯关解析
c++·python·算法·bfs·信息学竞赛
eggwyw2 小时前
C++深入浅出探索数据结构的原理
开发语言·c++
eggwyw2 小时前
C++深入浅出讲解希尔排序算法的实现
开发语言·c++