Counting Bits
来源:互联网 发布:工业控制网络视频 编辑:程序博客网 时间:2024/06/05 06:50
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]
.
Follow up:
- It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
- Space complexity should be O(n).
- Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
这一题意思是,给定一个数字num,求从0~num的二进制数中,分别含1的个数。如 7 = 111b,1的个数为3.
我们当然可以很容易在O(n*sizeof(integer))时间求出,只要对于每个数我们都单独求其1的个数。
可以用__builtin_popcount (int)函数直接求,或者自己写一个函数来求(令所求数为k):
int x = 1;
count = 0;
for (int i = 0; i < 32; i++){
count += x & k;
k = k >> 1;
}
return count;
因为整数有32位,故用32次迭代。
有没有办法在O(n)时间里求呢?当然有。使用动态规划的方法。
下面是一个例子
当n = 7时,vector如下:
0 1 1 2 1 2 2 3
我们按照如下划分开
1 | 1 2 | 1 2 2 3 |
分成3个区间。下一个区间大小为上一个区间的两倍。
我们定第一个区间标号为1,第二个区间标号为2。。。
2.0是第2个区间下标为0的数字,如上为1,3.2是第3个区间下标为2的数字,如上为2
我们容易发现:
3.0 = 2.0
3.1 = 2.1
3.2 = 2.0+1
3.3 = 2.1+2
同样,在第四个区间中,仍有
4.0 = 3.0 4.1 = 3.1 4.2 = 3.2 4.3 = 3.3
4.4 = 3.0+1 4.5 = 3.1+1 4.6 = 3.2+1 4.7 = 3.3+1
这个规律很容易在二进制数上进行解释,在这就不多说。
故我们得到如下规律
if (b < 上个区间大小)
f(a, b) = f(a-1, b)
else
f(a, b) = 1+ f(a-1, b % 上个区间大小)
我的代码如下:
vector<int> countBits(int num) {
vector<int> res(num+1);
if (num >= 0) res[0] = 0; //初始化最初的区间
if (num >= 1) res[1] = 1;
int base = 1; //第一个区间的起始位置
int offset = 0; //偏移量,f(a,b)中的b
int fore_size = 1; //上一个区间大小
int size = 2; //本区间大小
for (int i = 2; i <= num; i++){
if (offset < fore_size) //b < 上个区间大小
res[i] = res[base + offset++];
else if (offset < size){ //b >= 上个区间大小
res[i] = 1 + res[base+(offset%fore_size)];
offset++;
}
else{
base *= 2; //更换区间,前进一步
offset = 0; //偏移量重置
fore_size = size; //区间大小更新
size *= 2;
i--;
}
}
return res;
}
vector<int> res(num+1);
if (num >= 0) res[0] = 0; //初始化最初的区间
if (num >= 1) res[1] = 1;
int base = 1; //第一个区间的起始位置
int offset = 0; //偏移量,f(a,b)中的b
int fore_size = 1; //上一个区间大小
int size = 2; //本区间大小
for (int i = 2; i <= num; i++){
if (offset < fore_size) //b < 上个区间大小
res[i] = res[base + offset++];
else if (offset < size){ //b >= 上个区间大小
res[i] = 1 + res[base+(offset%fore_size)];
offset++;
}
else{
base *= 2; //更换区间,前进一步
offset = 0; //偏移量重置
fore_size = size; //区间大小更新
size *= 2;
i--;
}
}
return res;
}
阅读全文
0 0
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- Counting Bits
- 用c++简单的封装线程c中互斥锁
- PAT (Advanced Level) Practise 1120 Friend Numbers (20)
- C# ACCESS数据库操作类
- POJ2348 UVa10368 HDU1525 Euclid's Game【博弈】
- 144. Binary Tree Preorder Traversal
- Counting Bits
- linux --学习1
- ACache源码分析
- You called this URL via POST, but the URL doesn't end in a slash and you hav。。。
- MAC允许任何来源应用运行
- mysql查看执行计划
- JavaScript prototype
- Android数据存储——文件ANDsharepreferences
- 试题测试(错误)