持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的11天,点击查看活动详情
一、题目描述:
给你一个整数
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(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
- 你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount )
二、思路分析:
理论上是动态规划,但我说不太清楚,因为是找规律得到的,这个题就是个打表题。
- 因为都是从0开始的,所以最终返回的数组中第一个数字是0。这个数组的生成方法是:逐渐将数组长度加倍,通过将数组原来的每个元素+1,直接放在原数组后面达到长度加倍的效果;
- 举个例子:
- 一开始是数组长度为1:{0};将原数组{0}中所有元素+1后得到{1},将{0}和{1}拼接到一起得到{0,1};
- 数组长度为2:{0,1},所有元素+1得到{1,2},拼接后为{0,1,1,2};
- 依次类推长度为8时为{0,1,1,2,1,2,2,3}
- ......
三、AC 代码:
class Solution {
public:
vector<int> countBits(int n) {
vector<int> result(n+1);
result[0] = 0;
int base = 1;
for(int i = 1; i <= n; i++){
result[i] = result[i - base] + 1;
if(base * 2 == i + 1) base *= 2;
}
return result;
}
};