前n个数字种的二进制数中的1的个数

给定一个非负整数 n ,请计算 0n 之间的每个数字的二进制表示中 1 的个数,并输出一个数组。

示例 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

两种方法,一种就是对每一个数字进行处理,另一种就是使用动态规划

public int[] countBits(int n){
    // 大小为n+1是因为还有0
    int[] res = new int[n+1];
    for(int i = 0;i < n+1;i++){
        res[i] = getOne(i);
    }
    return res;
}
public int getOne(int n){
    int res = 0;
    while(n != 0){
        // 这一步是可以将二进制中最后一个1转化为0
        n = n&(n-1);
        res ++;
    }
    return res;
}

代码解析:我们想要知道一个二进制数中1的个数,我们除了对每一位的数字进行判断以外,我们还可以使用Brian Kernighan 算法,这个算法当n&(n)-1的时候,得到的结果是将n最低位的1转化为0

例如:

    n = 3;
    n的二进制表示:11
    n-1的二进制表示:10
    n&(n-1) = 10
    10相较11,最右边的1变成了0
    如果再次转化
    10&01 = 00

public int[] countBits(int n){
    // 大小为n+1是因为还有0
    int[] res = new int[n+1];
    res[]  = 0;
    for(int i = 1;i < n+1;i++){
        if(i%2 == 0){
            res[i] = res[i>>1];
        }else{
            res[i] = res[i-1] + 1;
        }
    }
    return res;
}

代码解析:通过对二级制数的分析,我们可以发现,奇数中二进制数种1的个数为当前奇数前一个偶数中个数+1(因为和偶数只是最低位多了一个1),偶数中个数和将当前偶数右移一位的偶数是一样的(因为多的一位是最低为,一定为0)

Brian Kernighan 算法:n&(n-1) = n将最右边的1转化为0得到的结果

二进制中1的个数的规律:奇数等于前一个偶数数目加一,偶数和当前偶数右移一位相同。

Original: https://www.cnblogs.com/foldn/p/16025580.html
Author: foldn
Title: 前n个数字种的二进制数中的1的个数

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579738/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球