Total Accepted: 29725
Total Submissions: 52050
Difficulty: MediumGiven 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.
Hint:You should make use of what you have produced already.
Divide the numbers in ranges like [2-3], [4-7], [8-15] and so on. And try to generate new range from previous.
Or does the odd/even status of the number help you in calculating the number of 1s?
计算在[0,num]范围内每个数字的二进制形式有多少个1存在,最粗暴的方法是从0开始,每个数字循环其32位,和1做与操作,看有多少个1存在。这种方法简单直接,虽然在形式上还是O(n)复杂度,但在实际操作上无疑是非常慢的,考虑到较小的数字实际上最高有效位仅仅几个,为了这个而循环32位,浪费了许多时间。
这道题的 tag 是 dynamic programming,某种程度上提示了我们很多。
这道题某种程度也很像是一道找规律的题,我们可以发现某种归还规律。
当 num 为0 时,位数为0;
num = 1 时,位数为1;
num = 2 时,位数为1;
num = 3 位数为 2;
可以发现每当过了2的n 次幂以后,之后的位数相当于从0开始重新计数+1(来源于整数次幂带来的1)
因此结果就非常直接
public class Solution {
public int[] countBits(int num) {
int[] dp = new int[num+1];
dp[0] = 0;
if(num == 0){
return dp;
}
dp[1] = 1;
int upper = 2;
for(int i = 2; i <= num; i++){
if(i == upper){
dp[i] = 1;
upper = upper*2;
continue;
}
int res = i - upper/2; // 超过2的 n 次幂以后,循环之前的数列
dp[i] = dp[res]+dp[upper/2];
}
return dp;
}
}
Runtime: 3 ms