LeetCode 338. Counting Bits的两种超简单方法解析

Description:

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.

Example 1:

Input: 2
Output: [0,1,1]

Example 2:

Input: 5
Output: [0,1,1,2,1,2]

Follow up:

  • It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
  • Space complexity should be O(n).
  • Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.

题目大意:计算0-num中每个数所对应的二进制中1的个数。

方法一:最简单粗暴,如果知道Java有相应API可以直接使用。

class Solution {
    public int[] countBits(int num) {
        int[] arr = new int[num+1];
        for(int i=0;i<num+1;i++){
            arr[i] = Integer.bitCount(i);
        }
        return arr;
    }
}

 Integer.bitCount(int i)的源码如下,有兴趣的可以研究一下:

/**
     * Returns the number of one-bits in the two's complement binary
     * representation of the specified {@code int} value.  This function is
     * sometimes referred to as the <i>population count</i>.
     *
     * @return the number of one-bits in the two's complement binary
     *     representation of the specified {@code int} value.
     * @since 1.5
     */
    public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

方法二:如果不知道API呢,是不是就没有简单的解法呢?当然不是。这道题目的标签是Dynamic Programming,如果不使用一点动态规划,是不是有点对不起命题人的良苦用心呢?

乍眼一看,一脸懵逼,这和动态规划根本就是驴头不对马嘴,没有一毛钱的关系啊?举个例子就明白:

十进制二进制
1001100100
1011100101
50110010

观察上面表格中的内容,1100100(100的二进制)、1100101(101的二进制)去掉最后一位,则惊奇的等于110010(100/2=50的二进制)。

其实,这并不是什么秘密。想想十进制,设一个数为x,100,101,102,~109去掉最后一位,也等于 10(x / 10的十进制),这不是同样的道理吗?

那么,i的二进制表示中由多少个1 = i的二进制表示中去掉最后一位以后1的个数 + i的二进制表示中最后一位1的个数

设:f[i]表示i的二进制表示中有多少个1,则有:

                            f[i] = f[i >> 2] + (i % 2)

即:本动态规划的动态转移方程。

显然本题初始条件为f(0) = 0;可以从0到num的顺序进行动态规划,下面直接看代码:

class Solution {
    public int[] countBits(int num) {
        int[] dp = new int[num + 1];
        for (int i = 1; i < num + 1; i++) {
            dp[i] = dp[i >> 1] + (i % 2);
        }
        return dp;
    }
}

这也完全符合题目Follow Up的要求,一次循环完成,线性时间复杂度O(n),空间复杂度 O(n)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

James Shangguan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值