动态规划+二进制运算

题目链接:

比特位计数  来自LeetCode

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

 

示例 1:

 

输入: 2

输出: [0,1,1]

示例 2:

 

输入: 5

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

 

解题方法参考LeetCode解题

方法一:

针对任意整数k,可以转为二进制.将k和k-1进行&运算.这样就会将最后一个是1的位变为0.每次将&的结果重新赋值给k.每一次赋值,进行计数+1.直到K变为了0,得到的计数值,就是当前数字中二进制1的个数.

例如:123:

        

  十进制 相邻位 &结果  
1 1111011 1111010 1111010  
2 1111010 1111001 1111000  
3 1111000 1110111 1110000  
4 1110000 1101111 1100000  
5 1100000 1011111 1000000  
6 1000000 0111111 0000000  

最后一共执行了六次位运算,所以二进制中1的结果为6.

遍历范围中的每个数,就可以得到最终结果.

代码:

public class Solution1 {
    public int[] countBits(int num) {
        int[] result = new int[num+1];
        for(int i = 0;i<=num;i++){
            result[i] = calcCnt(i);
        }

        return result;
    }

    private int calcCnt(int number){
        int cnt=0;
        while(number!=0){
            number &=(number-1);
            cnt++;
        }
        return cnt;
    }
}

方法二:

动态规划+从低往高计算.

二进制最基本的0和1,前面增加1,变为了(10)2=4,(11)2=3.

同样的,根据1~4的二进制,前面增加1,可以变为5~8.

00 0 100 4
01 1 101 5
10 2 110 6
11 3 111 7

所以可以通过递推公式求出范围中所有数字的1的个数.

       P(x+b) = P(x)+1,b=2m>x.

P(x)代表x中1的个数.

b表示增加的基数,这个基数一定是2的次幂.

仍旧按照上面例子来说:

(0,1)中1的个数是(2,3)中1的个数-2,

(0,3)中1的个数是(4,7)中1的个数-4.

 

java代码:

public class Solution2 {
    public int[] countBits(int num) {
        int[] res = new int[num+1];
        int i = 0;
        int b = 1;
        while(b<=num){
            while(i<b&&i+b<=num){
                res[i+b] = res[i]+1;
            }
            i = 0;
            b<<=1;
        }
        return res;
    }
}

方法三:

动态规划+数字移位.

对于一个数x,执行右移后会变为x/2.

如果x本身为偶数,右移后1的个数是不变的.

如果x本身是奇数,右移后,1的个数会少一个.

所以P(x) = P(x/2)+mod(x,2).

 

java代码:

public class Solution3 {
    public int[] countBits(int num) {
        int[] res = new int[num+1];
        for(int i = 0;i<=num;i++){
            res[i] = res[i/2]+i%2;
        }
        return res;
    }
}

方法四:

动态规划+最低的1位归零

实际内容与方法一相似.针对数字x,执行了x&(x-1)后,x的最低1的位会变为0;

所以P(x) = P(x&(x-1))+1;

从小到大进行所有数字遍历即可.

java代码:

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

 

posted @ 2021-04-30 15:14  Monstro  阅读(173)  评论(0)    收藏  举报