Java面试题——前n个数字二进制形式中1的个数

题目:输入一个非负数n,请计算0到n之间每个数字的二进制形式中1的个数,并输出一个数组。例如,输入的n为4,由于0,1,2,3,4的二进制形式中1的个数分别为0、1、1、2、1,因此输出数组【0,1,1,2,1】

对于很多人最先想到的暴力解法,就是使用一个for循环从0到n的每个整数i的二进制形式中1的个数。于是问题转换成如何求一个整数i的二进制形式中1的个数。

高效方法: 每次采用“i & (i-1)"将整数i的最右边的1变为零。整数i减去1,那么它最右边的1变成零。如果他的右边还有零,则右边所有的零都将变成1,而其左边的1变成零,以二进制的1100为例它减去1的结果为1011,1100和1011的位与运算正好是1000.二进制的1100最右边的1变为零,刚好结果就是1000.

public int[] countBits(int num){
    int[] result = new int[num+1];//存储第i位1的数目
    for(int i = 0; i <= num; i++){
        int j = i;
        while (j !=0){//判断所有的1是否都转变为零
            result[i]++;
            j = j & (j -1);//将最后一个一的位置变为零
        }
    }
    return result;
}

代码优化:分析可知,”i & (i - 1)”将i的二进制形式中最右边的1变成0,也就是说,整数i的二进制形式中1的个数比“i & (i - 1) "的二进制形式中1的个数多1.

public int[] countBits(int num){
    int[] result = new int[num+1];//存储第i位1的数目
    for(int i = 0; i <= num; i++){
        result[i] = result[i & (i-1)] + 1;
    }
    return result;
}

另外一种方法:根据“i/2“计算i的二进制形式中1的个数:

        如果正整数i时一个偶数,那么i相当于将”i/2“左移一位的结果,因此偶数i和”i/2"的二进制形式中的1的个数是相同的。如果i时奇数,那么i相当于将“i/2”左移一位后再加一,所以奇数i的二进制形式中1的个数比“i/2”多一个1。

public int[] countBits(int num){
    int[] result = new int[num+1];//存储第i位1的数目
    for(int i = 0; i <= num; i++){
        result = result[i>>1] + (i&1);
    }
    return result;
}

此代码段采用了“i>>1”计算“i/2”,用“i & 1”计算“i%2”。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值