每日一题-338. 比特位计数
题目
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
链接
tag : 按位运算 动态规划
按位运算复习
负数按照补码进行位运算
- 按位与运算符&
清零(特定位置0):0和任意与操作皆为0
取一个数中指定位:任意位和1进行与操作为本身
10101010 & 00001111 = 00001010 //取低4位
- 按位或运算符|
生1(特定位置1):1和任意位进行或操作皆为1
取一个数中指定位:任意位和0进行或操作为本身
- 异或运算符^
特定位翻转:1^0=1 1^1=1 ,利用1去翻转
与0异或保持原值:0^0=0 0^1=1
-
取反运算符~
-
左移运算符<<和右移>>运算符(有符号)
左右移相等于乘除2
左移:左边丢弃(溢出导致的精度丢失),右边补0
右移:右边丢弃,左边根据符号补0或者1
- 无符号右移>>>(左移本身就与符号无关)
右边丢弃,左边补0
-
复合赋值运算符
-
不同长度数据进行位运算:操作数右端对齐进行位运算,补齐部分根据符号
题解
直接求法-按位运算
class Solution {
public:
vector<int> countBits(int num) {
vector<int> Res(num+1,0);
for(int i=0;i<=num;i++){
int data=i;
int res=0;
while(data>0){
data&=(data-1); //去掉最右的1
res++;
}
Res[i]=res;
}
return Res;
}
};
位运算x&(x-1)
奇偶规律
偶数2k相对于奇数2k-1,其bit位的1增加,在最低位
偶数4k相对于偶数2k,其bit位的1数量不变,因为等于右移除2,但是最低位为0,不影响1的数量
class Solution {
public:
vector<int> countBits(int num) {
vector<int> Res(num+1,0);
//i=0可以跳过,其1bit数为0,作为整个推导的起始点
for(int i=1;i<=num;i++){
if(i%2==1){
Res[i]=Res[i-1]+1;
}else{
Res[i]=Res[i/2];
}
}
return Res;
}
};
来自题解区的大佬的思路,实在是太优美了。双消耗打败90%+
动态规划
利用前面x&(x-1)能去掉最右的1的特性(也仅仅去掉了最右的1,前面的部分在&下保持原样)
实现了动态规划
class Solution {
public:
vector<int> countBits(int num) {
vector<int> Res(num+1,0);
//i=0可以跳过,其1bit数为0,作为整个推导的起始点
for(int i=1;i<=num;i++){
Res[i]=Res[i&(i-1)]+1;
}
return Res;
}
};

浙公网安备 33010602011771号