阿里算法笔试模拟题精解之“一的个数”

查看题目:一的个数
给你两个数字 l、r,问在区间 [l,r] 内的所有数中,二进制表示下“1”的个数最
多的一个数是多少,如果有多个相同的,输出所有符合条件的数中最小的一个数。
输入一个整数 l, 和一个整数 r。(1<=l<=r<=10^9)
输出一个数字表示 [l,r] 内二进制下“1”的个数最多的数。如果有多个,输出符
合条件的数中最小的。
示例 1
输入:
5
10
输出:
7

解题思路:二进制
根据题意,本题的所有数字应从二进制角度考虑。
所求数字可分为两部分,高位部分和低位部分,高位部分的值等于 l, r 高位相等
的部分,在区间 [l,r] 中的所有数的高位部分都应该与其相等,即
high = r & (-1<
低位的部分计算过程如下:
如果 r-high 的值的二进制全为 1,则低位部分为 r-high。如果不是全为 1,则
低位部分为
( 1<<(count-1) ) - 1
给了解题思路没有给对应代码,解题方法有很多,以下是我的解题方法
方法1:当时没有按解题思路来解题的代码:
public static void main(String args[]) {
        int number = 6;
        int number2 =11;
        int min = minNumber(number,number2);
        System.out.println("区间"+number+"->"+number2+"二进制包含'1'最多的最小值是"+min);
    }

    private static int minNumber(int number, int number2) {
        int count = 0;              //包含1计数
        int max =0;                 //包含1最多的个数
        int maxCount =0;            //包含1最大的记录
        int min =Integer.MAX_VALUE; //包含1最多且最小的十进制数
        ArrayList<String> binary = new ArrayList<String>();
        Map<Integer,Integer> numList = new HashMap<>();//记录十进制数包含1的个数(用于打印)
        while (number <= number2){
            int calculate = number;
            //得到十进制的反向二进制数
            while (calculate != 0) {
                binary.add(valueOf(calculate % 2));
                calculate /= 2;
            }
            StringBuilder binaryNum = new StringBuilder();//用于打印
            Collections.reverse(binary);//将计算出的数组转向
            for (String s : binary) {
                binaryNum.append(s);
                if ("1".equals(s)){
                    count++;    //得到每个十进制数包含1的计数
                }
            }
            if (max != count ){
                max = Math.max(max, count);
                if (maxCount<max){  //旧的计数小于新的计数更新
                    maxCount = max;
                    min = number;
                }
            }else {
                min = Math.min(min,number); //如果相邻的两个十进制数包含相同数的1走这里
            }
            System.out.println(number+"二进制数为 "+binaryNum);
            numList.put(number,count);
            binary.clear(); //清空list
            count =0;       //计数归零
            number++;
        }
        System.out.println(numList.toString());
        return min;
    }

方法2:最后细看了解题思路自我感觉这可能是个笨方法,以下是按解题思路解题代码:

private static int minNumber(int number, int number2) {
        int count = 0;              //包含1计数
        int max =0;                 //包含1最多的个数
        int maxCount =0;            //包含1最大的记录
        int min =Integer.MAX_VALUE; //包含1最多且最小的十进制数
        ArrayList<String> binary = new ArrayList<String>();
        Map<Integer,Integer> numList = new HashMap<>();//记录十进制数包含1的个数(用于打印)
        while (number <= number2){
            int calculate = number;
            //在这里按解题思路中的方法可以很巧妙的计数
            while (calculate != 0) {
                //与操作 判断二进制最右一位是否为1(判断奇偶用的比较多)
                calculate = calculate & (calculate - 1);
                count++;
            }

            if (max != count ){
                max = Math.max(max, count);
                if (maxCount<max){  //旧的计数小于新的计数更新
                    maxCount = max;
                    min = number;
                }
            }else {
                min = Math.min(min,number); //如果相邻的两个十进制数包含相同数的1走这里
            }

            numList.put(number,count);
            binary.clear(); //清空list
            count =0;       //计数归零
            number++;
        }
        System.out.println(numList.toString());
        return min;
    }

方法2看起来更简洁且符合算法要求,欢迎评论指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值