每日一题-338. 比特位计数

题目

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
链接

tag : 按位运算 动态规划

按位运算复习

负数按照补码进行位运算

  1. 按位与运算符&

清零(特定位置0):0和任意与操作皆为0
取一个数中指定位:任意位和1进行与操作为本身
10101010 & 00001111 = 00001010 //取低4位

  1. 按位或运算符|

生1(特定位置1):1和任意位进行或操作皆为1
取一个数中指定位:任意位和0进行或操作为本身

  1. 异或运算符^

特定位翻转:1^0=1 1^1=1 ,利用1去翻转
与0异或保持原值:0^0=0 0^1=1

  1. 取反运算符~

  2. 左移运算符<<和右移>>运算符(有符号)

左右移相等于乘除2
左移:左边丢弃(溢出导致的精度丢失),右边补0
右移:右边丢弃,左边根据符号补0或者1

  1. 无符号右移>>>(左移本身就与符号无关)

右边丢弃,左边补0

  1. 复合赋值运算符

  2. 不同长度数据进行位运算:操作数右端对齐进行位运算,补齐部分根据符号

题解

直接求法-按位运算


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;
    }
};
posted @ 2021-03-03 21:14  tlamm  阅读(100)  评论(0)    收藏  举报