查看题目:一的个数
给你两个数字 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看起来更简洁且符合算法要求,欢迎评论指正。