leetcode:比特位计数

18 篇文章 0 订阅
4 篇文章 0 订阅

题目来源:力扣

题目描述:

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
================================================
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
=============================================
给出时间复杂度为O(n*sizeof(integer))的解答非常容易。但你可以在线性时间O(n)内用一趟扫描做到吗?

审题:

最简单的方法是检查每一整数的比特位,计算为1的个数.此处我们考虑其他时间复杂度更小的方法.
首先观察连续整数的比特数组,{0, 1, 10, 11, 100, 101, 110, 111},观察以上序列我们可以发现如下规律,2的比特位中1的个数等于0的比特位中1的个数+1,3的比特位中1的个数等于1的比特位中1的个数+1,4的比特位中1的个数等于0的比特位中1的个数+1,5的比特位中1的个数等于1的比特位中1的个数+1.我们使用 S [ i ] S[i] S[i]表示整数i中比特位为1的个数,则可以推导出如下公式:
S [ i ] = S [ i % 2 ( i n t ) l g 2 i ] + 1 S[i] = S[i \% 2^{(int)lg_{2}i}]+1 S[i]=S[i%2(int)lg2i]+1,且 S [ 0 ] = 0 , S [ 1 ] = 1 S[0] = 0, S[1] = 1 S[0]=0,S[1]=1.
基于以上最优子结构推导,我们可以使用动态规划算法自底向上依次计算S[0], S[1], …S[n].

还有另一中更简洁的方法,在看了此方法后,深感巧妙.所有整数可分为奇数和偶数两种,如果一个数是奇数,则其前一个数是偶数,并且该奇数位为1的个数等于前一偶数位为1个数加1,因为相较于前一偶数,除最低位由0变为1外,其余位均相同.如果当前数为偶数,则该偶数中位为1的个数等于该偶数除以2对应偶数中位为1的个数,因为除以2相当于将当前偶数右移一位,由于右移的最低位为0,因此移位后整数为1的个数不变.我们可以推导出如下最优子结构:
i f if if i & 1 = = 1 , S [ i ] = S [ i − 1 ] + 1 i\&1==1, S[i] = S[i-1]+1 i&1==1,S[i]=S[i1]+1
e l s e else else S [ i ] = S [ i > > 1 ] S[i] = S[i >> 1] S[i]=S[i>>1]

java算法:

class Solution {
    public int[] countBits(int num) {
        if(num == 0)
            return new int[]{0};

        int[] S = new int[num+1];
        S[0] = 0;
        S[1] = 1;
        for(int i = 2; i <= num; i++){
            int mod = (int)Math.pow(2, (int)(Math.log(i) / Math.log(2)));
            S[i] = S[i % mod] + 1;
        }
        return S;
    }
}
位运算版本
class Solution {

    public int[] countBits(int num) {
        if(num == 0)
            return new int[]{0};

        int[] S = new int[num+1];
        S[0] = 0;
        S[1] = 1;
        for(int i = 2; i <= num; i++)
            if((i & 1) == 0)
                S[i] = S[i >> 1];
            else
                S[i] = S[i-1] + 1;
        return S;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值