目录
1.1 题目
1.1.1 题目
给定一个非负整数 n
,请计算 0
到 n
之间的每个数字的二进制表示中 1 的个数,并输出一个数组。
1.1.2 示例
//示例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
*/
1.2 解题思想
1.2.1 暴力破解
从0到n进行遍历,可以通过一个函数f来计算当前数字i二进制位总共有几个1,利用Brian Kernighan 算法,可以在一定程度上进一步提升计算速度。Brian Kernighan算法思想:对于当前整数x,令x&=(x-1),记录计算的次数直到x为0。如果一个数y,y 的二进制表示中只有最高位是 1,其余都是 0,我们则称y是2的整数次幂,假设k=100...00,k-1=011...11,k&=(k-1),k=0,对于一个整数k1=011001011,可以看作是多个整数幂构成的每当对它k1&=k1-1,k1就会变为k1=011001010,不断的计算它运算的次数就可以得到结果
复杂度分析
- 时间复杂度:O(nlogn)
- 空间复杂度:O(n)
class Solution {
public int[] countBits(int n) {
int[] bits = new int[n + 1];
for (int i = 0; i <= n; i++) {
bits[i] = countOnes(i);
}
return bits;
}
public int countOnes(int x) {
int ones = 0;
while (x > 0) {
x &= (x - 1);
ones++;
}
return ones;
}
}
1.2.2 利用奇偶性的特点
从最低位开始对于bitcount[1]=1,bitcount[2]=1,bitcount[3]=2,bitcount[4]=1...,对于偶数k=1011..1100,k的最低位一定为0,当对k/2运算可以得到k/2=0101...110就是等同于向左移动一位(也可以写为k>>1),二进制位中1的总数没有变化,可以表示为bitcount[n]=bitcount[n/2]。对于奇数最低位一定为1,假设k=101...11,k>>1=0101...01,可以发现二进制位总数少1,可以表示为bitcount[n]=bitcount[n/2]+1。合并可以得到递推式为:bitcount[n]=bitcount[n>>1]+n&1。
复杂度分析
- 时间复杂度:O(n)
- 空间复杂度:O(n)
1.3 函数代码
public int[] countBits(int n) {
int[] res = new int[n+1];
res[0] = 0;
for(int i = 1; i <= n; i++){
res[i] = res[i>>1] + i % 2;
}
return res;
}