题目:
输入一个非负数n,请计算0到n之间每个数字的二进制形式中1的个数,并输出一个数组。例如,输入的n为4,由于0、1、2、3、4的二进制形式中1的个数为0、1、1、2、1,因此输出数组[0,1,1,2,1]
leetcode题目连接:https://leetcode.cn/problems/w3tCBm/
分析:
1、利用i&(i-1)计算
i变成i-1时,就是把最右边的1变成0, 同时把它右边的0都改为1。
将i与i-1进行位与计算,可发现i&(i-1)的1总是比i的1数量少一个,因为在1*前的1都保留下来,1*及其之后的位与计算结果都为0,所以相差1个数量,差的正是1*
Java代码实现:
class Solution {
public int[] countBits(int n) {
int[] count = new int[n+1]; //定义数组,存放1的数量
for(int i = 1; i <= n; i++){
count[i] = count[i&(i-1)] + 1; //i中1的数量比i&(i-1)多1
}
return count;
}
}
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)
2、利用“i/2”计算
如果i是偶数,i/2的二进制形式只是把1移动一位,1的数量没变,例如4=100,2=010
如果i是奇数,i的二进制形式中1的数量总比i-1多1,因为i的最低位为1,多出来的一个1就是最低位的这个1,例如5=101,4=100
i/2=(i-1)/2,例如7/2=6/2=3
因此可以得到如下:
count[i] = count[i/1],i为偶数
count[i] = count[i-1] +1 = count[(i-1)/2] +1 = count[i/2] +1,i为偶数
合并为:
count[i] = count[i/2] + i%2
i/2可以用i>>1实现
i%2可以用i&1实现
如果i为奇数,最低位一定为1,i&1为1
如果i为偶数,最低位一定为0,i&1为0
i&1的作用等同于i%2,但是位运算比求余运算更高效
Java代码实现:
class Solution {
public int[] countBits(int n) {
int[] count = new int[n+1]; //定义数组,存放1的数量
for(int i = 1; i <= n; i++){
count[i] = count[i>>1] + (i&1);
}
return count;
}
}
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)
代码执行结果:
以上为个人做题笔记,很多是自己的理解,若有错误还请各位大佬指出~