LeetCode-338. Counting Bits
Problem:
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.
Analysis:
题目大意:
给定一个非负整数num。对于每一个满足0 ≤ i ≤ num的数字i,计算其数字的二进制表示中1的个数,并以数组形式返回。
测试用例如题目描述。
进一步思考: 很容易想到运行时间 O(n*sizeof(integer)) 的解法。但你可以用线性时间O(n)的一趟算法完成吗? 空间复杂度应当为O(n)。
你可以像老板那样吗?不要使用任何内建函数(比如C++的__builtin_popcount)。
提示:
- 你应当利用已经生成的结果。
- 将数字拆分为诸如 [2-3], [4-7], [8-15]之类的范围。并且尝试根据已经生成的范围产生新的范围。
- 数字的奇偶性可以帮助你计算1的个数吗?
方法1 利用了位运算i&(i-1),这个运算可以去除最右边的1,思想是利用已经计算过的值再加1得到要计算的值。
public class Solution {
public int[] countBits(int num) {
int[] res = new int[num+1];
res[0]=0;
for(int i=1;i<=num;i++){
res[i]=res[i&(i-1)]+1;
}
return res;
}
}
方法2 是根据提示将数分为诸如 [2-3], [4-7], [8-15]之类的范围,在数满足2的n次方的时候记录这个范围中的最小数(这个范围的数都是在这个最小数的基础上增加)的1的个数和这个数的大小值。然后利用以前计算过的数进行DP。
public class Solution {
public int[] countBits(int num) {
if (num==0) return new int[]{
0};
int[] x=new int[num+1];
x[0]=0;
x[1]=1;
int seed=1;
for (int i=2;i<num+1;i++){
if (i==seed*2 ){
x[i]=1;
seed=i;
continue;
}
x[i]=x[i-seed]+1;
}
return x;
}
}
还没有评论,来说两句吧...