[字节秋招笔试]二进制1的个数

题目

输入正整数N,求从1到N所有数包含的二进制1的个数。

题解

这是一道找规律题==。
例:对于nums=1101(2进制)的方法compute(nums):

  • 可以把它分成[1000(二进制),1101(2进制)]中二进制1的个数、[000(二进制),111(二进制)]中二进制1的个数两部分求解,再将两部分相加。
  • 第二部分可以看做是m位二进制可表示的所有数所包含的二进制1的个数,找规律可得,ansPart2=Math.pow(2,bitPosLen-1)*bitPosLen
  • 第一部分则可以递归计算:ansPart1=[1000(二进制),1101(2进制)]范围内二进制最高位包含的二进制1个数+compute(101(二进制))。

代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int t=in.nextInt();
        while(t--!=0){
            int num=in.nextInt();
            long ans=bitOneCntContains(num);
            System.out.println(ans);
        }
    }
    
    private static long bitOneCntContains(int nums){
        if(nums<=1){
            return nums==1?1:0;
        }
        
        // 寻找二进制最高位
        int bitPos=0;
        for(bitPos=0;bitPos<100;++bitPos){
            if(Math.pow(2,bitPos)>nums){
                break;
            }
        }
        int bitHeighestPos=bitPos-1;// nums二进制最高位
        
        // 计算ansPart1(例如:对于nums=1101(2进制),ansPart1=[1000(二进制),1101(2进制)]中二进制1的数量)
        int minNum=(int)Math.pow(2,bitHeighestPos);// 对应二进制最高位为1,其他位为0的数字
        int cnt=nums-minNum+1;// 从0到nums,最高位包含1的数量
        long ansPart1=bitOneCntContains(nums-minNum)+cnt; 
        
       // 计算ansPart2(例如:对于nums=1101(2进制),ansPart2=[000(二进制),111(二进制)]中二进制1的数量)
        int bitPosLen=bitHeighestPos;// 除了最高位二进制的位数
        long ansPart2=(long)Math.pow(2,bitPosLen-1)*bitPosLen;// 找规律可得
        return ansPart1+ansPart2;
    }
}

posted on 2020-07-22 21:07  coding_gaga  阅读(273)  评论(0编辑  收藏  举报

导航