算法题每日一练---第42天:比特位计数

464 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、问题描述

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组ans 作为答案。

题目链接:比特位计数

二、题目要求

样例

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

考察

1.动态规划中等题型,规律归纳有点难
2.建议用时15~30min

三、问题分析

今天是刷动态规划的第9天了,勉强算个入门动态规划了吧!之前没做过动态规划的,可以看看这一片入门题解,介绍比较详细:算法题每日一练---第34天: 青蛙跳台阶

对于这道题目,一开始,遇到这一题根本没想到用递归,因为脑子笨规律找不到。直接for循环一个个转换成2进制,对有1的数字进行计数,最后输出结果。

3.png

提交也成功通过了,只是有点耗费时空复杂度。

4.png 做出了就行,但我看了关于动态规划的题解,我沉默了,真TM的好!

接下来接着用我们的三步走,老套路了,开干:

第一步 含义搞懂:

题目要求求出二进制中1的个数,那么dp[i]就代表i转换成二进制之后,存储的数字。

第二步 变量初始:

这一题只需要初始一个变量,那就是dp[0]=0

第三步 规律归纳:

          0 --> 0
1 --> 1
          2 --> 1
3 --> 2
          4 --> 1
5 --> 2
          6 --> 2
7 --> 3
          8 --> 1
9 --> 2
          10 --> 2

我把前十个数字分成奇数、偶数分别列出来,看看有什么区别:

如果i是偶数,dp[i]=dp[i/2]; 因为是2进制,偶数除以一个2,也没有多出来一个1。
如果i是奇数,dp[i]=dp[i/2]+1;奇数就是比偶数多出来一个1

三步走,打完收工!

四、编码实现

class Solution {
public:
    vector<int> countBits(int n) {
        long long int i,k;//初始化变量
        vector<int>dp(n+1);//定义数组
        dp[0]=0;//第二步 变量初始
        for(i=1;i<=n;i++)
        {
            if(i%2==0)//第三步 规律归纳
                dp[i]=dp[i/2];
            else
                dp[i]=dp[i/2]+1;
        }
        return dp;//输出结果
    }
};

五、测试结果

5.png

4.png 好家伙,执行用时直接少了2/3