leetcode 338. Counting Bits
Question
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1’s in their binary representation and return them as an array.
Example
For num = 5 you should return [0,1,1,2,1,2].
问题
给定一个非负整数num,返回[1,num]区间内每个数字的二进制串中1的个数。
要求
- one-pass
- O(n)时间复杂度
- O(n)空间复杂度
- 不准用__builtin_popcount 之类的内建函数
分析
首先想到的方法,肯定是依次计算每个数字的二进制串中1的个数。计算数字的二进制串中1的个数是一个经典问题,复杂度是O(n),n是二进制串的长度。显然这样整体的复杂度就是O(n*bitof(integer)),不符合要求。
然后想办法找结果列表的规律:0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4 1…好像并没有什么规律。
那么能不能利用已经计算出来的结果呢?可以的。假设countOneBit是获取1的个数的操作,那么countOneBit(N) = countOneBit(N >> 1) + N & 1。
举个例子,假设现在要计算7的二进制串中1的个数。7的二进制串是0111,可以分成两块011 1,这两块分别对应上面的公式的两部分。
代码
vector<int> countBits(int num) {
vector<int> bits;
bits.push_back(0);
for (int i = 1; i <= num; i++)
{
int bit = bits[i >> 1] + (i & 1);
bits.push_back(bit);
}
return bits;
}
总结
当对集合中的每个元素进行相同操作时,可以考虑使用前面已经操作完成的结果。有点动态规划的意思。