剑指offer》面试题3:前n个数字二进制形式中一的个数

文章介绍了如何计算0到n之间每个数字二进制表示中1的个数,提供了三种不同的代码实现,分别是通过i&(i-1)消除最右边的1,利用位运算直接计算,以及根据数字奇偶性与i/2的关系进行计算。这些方法优化了时间复杂度,从O(nk)降低到O(n)。
摘要由CSDN通过智能技术生成

最近在看面试题,整理了书上的解题思路和代码,方便有需要的读者学习

题目:

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

分析:

  • 我们可以用i&(i-1)将二进制最右边的1变成0

    代码实现:

    public static int []countBits(int num){
            int[]result =new int [num + 1];//用于储存0-num的1的个数
            for(int i=0;i<=num;++i){//循环遍历0-num的二进制数
                int j=i;//将i赋值给j
                while(j!=0){//每次都去最右边的一个一,直到变成0
                    result[i]++;//统计1的个数
                    j=j&(j-1);//将最右边的1变成0
                }
            }
            return result;
        }

    如果一个整数右k位,那么while循环要执行k次,因此上面代码的时间复杂度为O(nk)

  • 整数i1的个数等于i&(i-1)1的个数加1

    代码实现:

    public static int []countBits(int num){
            int[]result =new int [num + 1];//用于储存0-num的1的个数
            for(int i=0;i<=num;++i){//循环遍历0-num的二进制数
                result[i]=result[i&(i-1)]+1;//比去掉最右边的1的数大1
            }
            return result;
        }

    去掉了一个while循环时间复杂度为O(n)

  • 计算i/2中1的个数

  • 偶数和i/2中1的个数相同

  • 奇数比i/2中1的个数多一个

    代码实现:

    public static int []countBits(int num){
           int []result =new int [num=+1];
           for(int i=1;i<=num;i++){
               result[i]=result[i>>1]+(i&1);
    ​
           }
           return result;
        }

    虽然时间复杂度也是O(n),但是位运算比求和除法更加高效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值