比特位计数

文章介绍了三种方法计算给定整数n的二进制表示中1的个数:Brainkernighan算法通过逐位与减法,动态规划方法包括最高有效位和最低有效位策略。分别展示了C++类Solution中的实现代码。
摘要由CSDN通过智能技术生成

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

方法一: 使用Brain kernighan算法统计二进制中1的个数

Brain kernighan算法:通过x&(x-1)将x的最后一位变成0,然后不断重复相与的过程直到x变成0,统计相与的次数就是x二级制中1的个数了

class Solution {
public:
    int countOnes(int x){
        int ones=0;
        while(x>0){
            x&=(x-1);
            ones++;
        }
        return ones;
    }
    vector<int> countBits(int n) {
        vector<int> count;
        count.resize(n+1);
        for(int i=0;i<=n;i++){
            count[i] = countOnes(i);
        }
    return count;
    }
};

方法二:动态规划,最高有效位

假设我们现在要求的是数i的二进制比特位中1的个数,那么在0<=j<=i中如果存在一个数其二进制比特位加一个1就是i的二进制数,那么就i的二进制比特位中1的个数就等于:

bits[i]=bit[j]+1

那么问题就变成找到这个j,方法就是对于正整数x来说,找到小于等于x并且是2的整数次幂的最大数y,也就是找到x的最高有效位对应的数是什么,比如9的二进制数是1001,最高有效位对应的是1000也就是十进制的8,那么我们要求的j就是等于x-y,bits[9] = bits[9-8]+1

这是为什么呢?因为最高有效位对应的二进制数与要求的正整数的二进制数来说只有最高位的1是一样的其他全是0,那么我们用x-y的二进制数就比x少了最高位那个1,但是其他位数和j的二进制数是一样的,因此就可以用bits[x] = bits[x-y]+1来表示

代码如下:

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> bits;
        bits.resize(n+1);
        int hightBit=0;
        for(int i=1;i<=n;i++){
            if((i&(i-1))==0)
            hightBit = i;
            bits[i] = bits[i-hightBit] + 1;
        }
        return bits;
    }
};

方法三:动态规划,最低有效位

第二种方法用了最高有效位的方法即是通过删除最高位的1来统计目标个数,那么最低有效位就反过来,假设现在要求x的二进制中1的个数,那么

对于正整数 x,将其二进制表示右移一位,等价于将其二进制表示的最低位去掉,得到的数是 ⌊x/2⌋,那么如果x是偶数的话,bits[x]=bits[⌊x/2⌋],如果x是奇数的话,bits[x]=bits[⌊x/2⌋]+1

class Solution {
public:
    vector<int> countBits(int n) {
        vector<int> bits;
        bits.resize(n+1);
        int hightBit=0;
        for(int i=1;i<=n;i++){
            bits[i] = bits[i/2] + i%2;
        }
        return bits;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值