LeetCode 0338. 比特位计数
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 0338. 比特位计数相关的知识,希望对你有一定的参考价值。
【LetMeFly】338.比特位计数:三种方法求一个数二进制下有多少个1
力扣题目链接:https://leetcode.cn/problems/counting-bits/
给你一个整数 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 <= 105
进阶:
- 很容易就能实现时间复杂度为
O(n log n)
的解决方案,你可以在线性时间复杂度O(n)
内用一趟扫描解决此问题吗? - 你能不使用任何内置函数解决此问题吗?(如,C++ 中的
__builtin_popcount
)
写在前面
本篇题解的三种方法不论哪一种,大致思路就是对于某个数,单独求出其二进制下有多少个1。
每个数的求解是相互独立的,求这一个数的时候没有用到上一个数的结果。
方法一:每次取最低位
对于一个数 n n n,在 n ≠ 0 n\\neq0 n=0时,不断取出当前 n n n的最低位,判断是否为1(KaTeX parse error: Expected 'EOF', got '&' at position 2: n&̲1)
之后,将 n n n的最低位丢弃(右移即可, n > > 1 n>>1 n>>1)
这样就统计出了 n n n在二进制下有多少个1。
- 时间复杂度 O ( n log 2 n ) O(n\\log_2 n) O(nlog2n)
- 空间复杂度 O ( 1 ) O(1) O(1),力扣算法答案不计入空间复杂度
AC代码
C++
不为0时取最低位,时间/空间超越:7.24%,55.59%
class Solution
private:
int __LetMeFly_popcount(int n)
int ans = 0;
while (n)
if (n & 1)
ans++;
n >>= 1;
return ans;
public:
vector<int> countBits(int n)
vector<int> ans(n + 1);
for (int i = 0; i <= n; i++)
ans[i] = __LetMeFly_popcount(i);
return ans;
;
方法二:借助内置函数__builtin_popcount
对于一个数 n n n,我们可以直接使用内置函数__builtin_popcount(n)来求出n在二进制下有多少个1
有些编译器不支持上述操作,但是力扣是支持的
- 时间复杂度 O ( n log 2 n ) O(n\\log_2 n) O(nlog2n)
- 空间复杂度 O ( 1 ) O(1) O(1),力扣算法答案不计入空间复杂度
AC代码
C++
内置__builtin_popcount,时间/空间超越:83.71%,56.81%
class Solution
public:
vector<int> countBits(int n)
vector<int> ans(n + 1);
for (int i = 0; i <= n; i++)
ans[i] = __builtin_popcount(i);
return ans;
;
方法三:借助lowbit
对于一个数 n n n,我们可以巧妙借助 l o w b i t lowbit lowbit来快速取出 n n n中的1
l o w b i t lowbit lowbit可以在 O ( 1 ) O(1) O(1)的复杂度内求出:一个数二进制下第一个1开始到二进制下最后一位 所组成的数。
说人话就是:
假如 n = 6 ( 11 0 2 ) n=6(110_2) n=6(1102),那么 l o w b i t ( 6 ) lowbit(6) lowbit(6)就等于 1 0 2 10_2 102,也就是十进制下的 2 2 2
这样,每次求得 l o w b i t lowbit lowbit后再减去之,就能每次消灭一个 1 1 1
二进制下有 k k k个 1 1 1的一个数 n n n只需要进行 k k k次运算就能求得答案。
具体原理可参考我之前的笔记:https://letmefly.xyz/Notes/ACM/Template/lowbit.html
喜欢了可以给个Star
- 时间复杂度 O ( n K ) O(n K) O(nK),其中 K K K是 n n n个数平均的“二进制下1的个数”
- 空间复杂度 O ( 1 ) O(1) O(1),力扣算法答案不计入空间复杂度
AC代码
C++
借助lowbit,时间/空间超越:83.71%,96.33%
class Solution
private:
int __LetMeFly_popcount_byLowbit(int n)
int ans = 0;
while (n)
n -= (n & -n);
ans++;
return ans;
public:
vector<int> countBits(int n)
vector<int> ans(n + 1);
for (int i = 0; i <= n; i++)
ans[i] = __LetMeFly_popcount_byLowbit(i);
return ans;
;
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/127087581
以上是关于LeetCode 0338. 比特位计数的主要内容,如果未能解决你的问题,请参考以下文章