小于n的最大数
题目描述: 数组A中给定可以使用的1~9的数,返回由A数组中的元素组成的小于n(n > 0)的最大数。例如:A = {1, 2, 4, 9},n = 2533,返回2499。
测试用例:
A = {1, 2, 4, 9}
n = 2533
输出 = 2499
A = {4, 2, 9, 8}
n = 988822
输出 = 988499
A = {9, 8}
n = 9
输出 = 8
A = {9, 6, 3, 5}
n = 56449
输出 = 56399
思路: 实际上数只有十个,那我们贪心就好了,我们首先匹配这个数 ,如果每一位都在这个数组中存在,就修改最小的一位,如果不就把最高的不能匹配的位之后变成数组中最大值,这一位找一个小的数代替
public class MainTest {
public static void main(String[] args) {
System.out.println(maxN(new int[]{1, 2, 4, 9}, 2533));
System.out.println(maxN(new int[]{4, 2, 9, 8}, 988822));
System.out.println(maxN(new int[]{9, 8}, 8));
System.out.println(maxN(new int[]{9, 6, 3, 5}, 56449));
System.out.println(maxN(new int[]{1,2,3,4,5,6,7,8},8363065));
}
// 贪心加二分
public static int maxN(int[] digits,int n){
Arrays.sort(digits);
String str= n + "";
// 从最高位开始寻找小于等于当前位的数
boolean less = false;
int res=0;
for(int i=0;i<str.length();i++){
int num = str.charAt(i)-'0';
if(less) {
res=res*10+(digits[digits.length-1]);
continue;
}
// 二分寻找小于等于num的第一个数
int r = binarySearch(digits,num,i<str.length()-1 ? str.charAt(i+1)-'0' : digits[0]);
// 1. 存在小于当前位的数,后续位之间取最大值
if(r<num){
res=res*10 + r;
less=true;
}
// 2. 存在等于当前位的数,继续寻找小于后续位的数
else if(r==num){
res=res*10 + r;
}
// 3. 不存在小于当前位的数,返回-1
else return -1;
}
return res;
}
// 返回小于等于target的第一个数
public static int binarySearch(int[] digits,int target,int next){
// 如果下一个数比digits数组中任何一个数都要小,那么当前target只能找小于的数,不能找等于的数
if(next<digits[0]) target--;
int b=0,e=digits.length-1;
while(b<=e){
int m=(b+e)>>1;
if(e-b<=1){
if(digits[e]<=target) return digits[e];
if(digits[b]<=target) return digits[b];
return digits[b];
}else if(digits[m]==target) return target;
else if(digits[m]>target) e=m-1;
else b=m;
}
return digits[b];
}
}
