小于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];
    }
}

全部评论
有意思
1 回复 分享
发布于 2023-12-26 17:35 陕西
贪心的话有问题 ,比如这个用例,打印出来就是67899 public static void main(String[] args) { int []nums={5,6,7,8,9}; int n=678912; System.out.println(maxN(nums,n)); }
点赞 回复 分享
发布于 03-27 00:00 河南
贴一个回溯 + 剪枝 实际时间复杂度应该很低 每一位数最多两种可能O(2^9) 欢迎大佬指正 #include<bits> using namespace std; typedef long long LL; typedef pair<int> PII; int solve(vector<int> nums, int n){ sort(nums.begin(), nums.end()); nums.erase(unique(nums.begin(), nums.end()), nums.end()); int m = nums.size(); int res = 0; string target = to_string(n); int len = target.size(); function<bool> dfs = [&](int x){ if(x == len && res < n){ if(res == 0) return false; return true; } for(int i = m - 1; i >= 0; i --){ if(res + nums[i] * (int) pow(10, len - x - 1) >= n) continue; res += nums[i] * (int)pow(10, len - x - 1); // cout << res << "\n"; if(dfs(x + 1)) return true; res -= nums[i] * (int)pow(10, len - x - 1); } if(x == 0){ res = 0; if(dfs(x + 1)) return true; } return false; }; if(dfs(0)) return res; return -1; } int main() { vector<int> nums = {6, 9, 3, 5}; cout << solve(nums, 56449) << "\n"; } </int></bool></int></int></bits>
点赞 回复 分享
发布于 02-14 17:21 湖北
一些边界条件没考虑 比如 1000 9 应该输出999
点赞 回复 分享
发布于 2024-07-25 12:37 北京
if(next
点赞 回复 分享
发布于 2024-07-25 12:32 北京

相关推荐

评论
8
32
分享

创作者周榜

更多
牛客网
牛客企业服务