比特位计数
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。
示例 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的个数
public int[] countBits1(int n) {
int[] nums = new int[n + 1];
for(int i = 0;i < nums.length;i++){
int count = 0;
// 统计每个数二进制中1的个数
// 右移并与1相与,等于1就加1
for(int j = 0;j < 32;j++){
if(((i >> j) & 1) == 1){
count++;
}
}
// 赋值
nums[i] = count;
}
return nums;
}
解法二:
先举个例子,下面列出0-9的二进制,
0 --- 0000 1 --- 0001 2 --- 0010 3 --- 0011
4 --- 0100 5 --- 0101 6 --- 0110 7 --- 0111
8 --- 1000 9 --- 1001
从上面列举出来的数可以看出,如果是奇数,那么它的二进制中1的个数就是它前面偶数的二进制中1的个数加1(偶数的二进制最后一位一定是0,它比前面的数大1,那么1就在最后一位);如果是偶数的话,那么它的二进制中1的个数就和它除以2后那个数一样多,为何这么说呢?因为偶数的二进制最后一位都是0,那么除以2就是将该数右移1位,这个并不影响该数的二进制中1的个数。代码如下:
public int[] countBits1(int n) {
int[] nums = new int[n + 1];
for(int i = 0;i < nums.length;i++){
if(nums[i] % 2 == 0){
nums[i] = nums[i / 2];
}else{
nums[i] = nums[i-1] + 1;
}
}
return nums;
}
其实if-else可以优化成nums[i] = nums[i >> 1] + (i & 1)
举个例子说明一下,当i等于5时,那么nums[5] = nums[5 >> 1] + (5 & 1) = nums[2] + 1;它和上面else内容一致,因为nums[4] == nums[2],所以说,你加nums[2]和加nums[4]是一个道理;当i等于6时nums[6] = nums[6 >> 1] + (6 & 1) = nums[3] + 0 = nums[3];
下面附上代码:
public int[] countBits1(int n) {
int[] nums = new int[n + 1];
for(int i = 0;i < nums.length;i++){
nums[i] = nums[i >> 1] + (i & 1);
}
return nums;
}