栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

338.比特位计数

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

338.比特位计数

给你一个整数n,对于0<=i<=n,计算其二进制中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

方法一:Brian Kernighan 算法

最直观的做法是对从 00 到 nn 的每个整数直接计算「一比特数」。每个int 型的数都可以用 32 位二进制数表示,只要遍历其二进制表示的每一位即可得到 1 的数目。Brian Kernighan 算法,可以在一定程度上进一步提升计算速度。Brian Kernighan 算法的原理是:对于任意整数 x,令 x=x & (x−1),该运算将 x 的二进制表示的最后一个 1 变成 0。因此,对 x 重复该操作,直到 x 变成 0,则操作次数即为x 的「一比特数」。对于给定的 n,计算从 0 到 n 的每个整数的「一比特数」的时间都不会超过 O(logn),因此总时间复杂度为 O(nlogn)。


int coutnoes (int x) {     int ones=0;     while(x>0)     {         x&=x-1;         ones++;     }     return ones; } int* countBits(int n, int* returnSize){     int *res=(int *)malloc(sizeof(int)*(n+1));     *returnSize=n+1;     for (int i=0;i<=n;i++)     {         res[i]=coutnoes(i);     }     return res; } 时间复杂度:O(nlogn) 空间复杂度:O(1)
解法二:动态规划——最高有效位

方法一需要对每个整数使用O(logn)的时间计算【—比特数】。可以换一个思路,当计算i的【—比特数】时,如果存在0<=j<=i,j的【—比特数】已知,且i和j相比,i的二进制表示之多一个1,则可以快速得到i的—比特数。

令bits[i]表示i的[-比特数],则上述关系表示为bits[i]=bits[j]+1。

对于正整数x,如果可以知道最大的正整数y,使得y<=x,且y是2的整数次幂,则y的二进制表示中只有最高为是1,其余是0,此时称y为x的[最高有效位]。令z=x-y,显然0<=z

为了判断一个正整数是不是2的整数次幂,可以利用方法一中提到的按位与运算性质。如果正整数 y 是 2 的整数次幂,则 y 的二进制表示中只有最高位是 1,其余都是 0,因此 y&(y-1)=0。由此可见,正整数 y 是 2 的整数次幂,当且仅当 y & (y−1)=0。

显然,0 的「一比特数」为 0。使highBit 表示当前的最高有效位,遍历从 1 到 n的每个正整数 i,进行如下操作。如果 i&(i-1)=0,则令highBit=i,更新当前的最高有效位。i 比 i−highBit 的「一比特数」多 1,由于是从小到大遍历每个整数,因此遍历到 i 时,i−highBit 的「一比特数」已知,bits[i]=bits[i−highBit]+1。


int* countBits(int n, int* returnSize){

    int highbit=0;

    int *bit=(int *)malloc(sizeof(int)*(n+1));

    *returnSize=n+1;

    bit[0]=0;

    for (int i=1;i<=n;i++)

    {

        if ((i&(i-1))==0)

        {

            highbit=i;

        }

        bit[i]=bit[i-highbit]+1;

    }

    return bit;

}

时间复杂度:O(n) 空间复杂度:O(1)
方法三:动态规划——最低设置位

定义正整数 x 的「最低设置位」为 x 的二进制表示中的最低的 1 所在位。例如,1010 的二进制表示是 1010_(2)  10(2),其最低设置位为 2,对应的二进制表示是 10_{(2)}10 (2) 。

令y=x & (x−1),则 y 为将 x 的最低设置位从 1 变成 0 之后的数,显然 0≤y

int* countBits(int n, int* returnSize) {

    int* bits = malloc(sizeof(int) * (n + 1));     *returnSize = n + 1;     bits[0] = 0;     for (int i = 1; i <= n; i++) {         bits[i] = bits[i & (i - 1)] + 1;     }     return bits; } 时间复杂度:O(n) 空间复杂度:O(1)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1019035.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号