携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
一、题目描述:
给你一个整数 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 进阶:
-
很容易就能实现时间复杂度为 的解决方案,你可以在线性时间复杂度 内用一趟扫描解决此问题吗?
-
你能不使用任何内置函数解决此问题吗?(如,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)