[更文刷题] 338. 比特位计数]

109 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

一、题目描述:

338. 比特位计数

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

示例 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 <= 10^5   进阶:

  • 很容易就能实现时间复杂度为 O(nlogn)O(n log n) 的解决方案,你可以在线性时间复杂度 O(n)O(n) 内用一趟扫描解决此问题吗?

  • 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount )

二、思路分析:

最容易想到的当然是 暴力 的解法!

那么如何计算n的二进制表示中1的个数呢?
我们从右向左看,找到第一个为1的bit位,将这一位置为0.
重复上述过程,统计操作的次数,就得到了1的个数.
那么如何实现上述操作呢?

我们不妨考虑下n和n-1之间的关系
20=10100
19=10011
看到木有,从右向左看第一1以及之后的bit位恰好相反,而在这个1之前的bit位不变.
因此20&19的结果,由二进制表示,可以算出为10000,我们将最右边的1去掉了,重复该过程.直到n变为0

三、AC 代码:

    vector<int> countBits(int num) {
        vector<int> ans(num+1);
        for(int i=1;i<=num;i++){
            ans[i]=cnt(i);
        }
        return ans;
    }
    int cnt(int n){
        int sum=0;
        while(n){
            sum+=1;
            n&=(n-1);
        }
        return sum;
    }

四、参考:

纯c,遍历,动态规划,超级详细,个人见解 - 比特位计数 - 力扣(LeetCode)

【仗剑骑士】C++, 两种方法实现O(n)时间复杂度, 统计规律+动态规划+338. 比特位计数 - 比特位计数 - 力扣(LeetCode)