比特位计数(力扣第338题)

338.比特位计数

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

示例 1:

输入: 2
输出: [0,1,1]

示例 2:

输入: 5
输出: [0,1,1,2,1,2]

分析:

第一种方法

暴力法:遍历0~num范围的所有数字,然后逐个统计其中1的个数

 public int[] countBits(int num) {

        int n = num + 1;
        int[] res = new int[n];
        if (num == 0){
            return res;
        }
        for (int i = 1; i < n; i++) {
            int count = 0;
            int curNum = i;
            while (curNum != 0){
                int temp = curNum & 1;
                if (temp == 1){
                    count++;
                }
                curNum >>= 1;
            }

            res[i] = count;
        }
        return res;
    }

可以使用Java的内置函数改进一下:

    public int[] countBits2(int num) {

        int n = num + 1;
        int[] res = new int[n];
        if (num == 0){
            return res;
        }
        /*
        static int Integer.bitCount(n); 统计n的二进制数中1的数量
         */
        for (int i = 1; i < n; i++) {

            res[i] = Integer.bitCount(i);
        }
        return res;
    }

第二种方法:动态规划

1	001
2	010
3	011
4	100
5	101
6	110
7	111

​ 寻找状态转移函数,求i的含有1的个数,可以通过之前已经求出的结果来求,那么需要先找出与其有关的小于i的数,可知i&(i-1)表示消除i中最右边的那个1,那么一定小于i。

​ 比如 2&1=0,3&2=2,4&3=0,5&4=4,6&5=4,7&6=6;

​ 而2中1的个数是1,3中1的个数是2,4中1的个数是1,5中1的个数是2,6中1的个数是2,7中1的个数是3;

​ 所以根据规律,状态转移函数为 f(i) = f(i&(i-1)) + 1

    public int[] countBits(int num) {
    int[] ret = new int[num + 1];
    for(int i = 1; i <= num; i++){
        ret[i] = ret[i&(i-1)] + 1;
    }
    return ret;
    }

参考:https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode 题解 - 位运算.md#11-实现整数的加法

posted @ 2020-12-04 18:06  有心有梦  阅读(82)  评论(0编辑  收藏  举报