小于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 北京

相关推荐

12-12 10:14
复旦大学 Java
点赞 评论 收藏
分享
从&nbsp;11&nbsp;月开始找第二段日常实习前前后后大概面了&nbsp;20&nbsp;多场,过程中又有了一些新的体会,和大家一起分享一下。1.&nbsp;&nbsp;一定一定,在没发&nbsp;offer&nbsp;前(即使&nbsp;oc&nbsp;了)要继续去投递和面试。2.&nbsp;在&nbsp;oc&nbsp;之后也不要立刻把之前已经拿到的&nbsp;offer&nbsp;拒掉,能拖就拖。主包原本已经拿了&nbsp;momenta&nbsp;和&nbsp;soul&nbsp;的&nbsp;offer,但是由于等腾讯&nbsp;csig&nbsp;的&nbsp;offer&nbsp;审批,然后拒掉了这俩,结果审批一周后流程结束,且没有任何通知消息•ᴗ•💧此时只能重新投递简历,等待约面,重新走流程,这一步其实是比较耗时间的,因为约面也很看运气和机遇。3.&nbsp;算法题大部分依然是&nbsp;hot100&nbsp;的&nbsp;codetop&nbsp;前五页,字节腾讯和小红书会有一些自创题,这一块可以多参考牛客的面经多积累4.&nbsp;面试是最好的老师,每次面试完都能套一些项目和实习经历有关的新的问题,另外面试多了之后,自己不会那么怯场,会感觉面试比较放松,当做是和面试官的一次交流,即使是小厂也可以当练手面试,只要有机会就去面5.&nbsp;有实习经历的同学,一定要把实习做的需求搞清楚,我参加的面试,基本上&nbsp;90%&nbsp;的面试,有&nbsp;90%&nbsp;的时间都在聊实习的相关问题,八股很少。有的时候会具体到消息队列怎么配置的,几个实例,几个&nbsp;partition&nbsp;这类的问题,或者&nbsp;qps&nbsp;多少,压测性能,搜索准确率,如何量化某个指标,还有些会涉及到类似于产品视角的问题,比如&nbsp;AB&nbsp;实验为什么这样配置,你觉得用户哪些体验能作为埋点这类的问题下面是一些面过的厂和感受:1.&nbsp;soul&nbsp;(oc&nbsp;拒掉)一面&nbsp;二面&nbsp;hr&nbsp;面都很快通过,感觉只要你有一段实习经历,并且把自己的实习的内容描述的清楚就能拿2.京东零售(oc&nbsp;拒掉)同一个大部门一面挂了两次,然后又被捞了第三次,然后一周内推进完流程。京东整体面试的感觉是如果对你感兴趣,面试的拷打强度很低,会花很多时间向你介绍业务,或者闲聊3.momenta(oc&nbsp;拒掉)做内部的数据平台,感觉最近应该是比较缺人,特别是北京的岗位,可能还会涉及到&nbsp;agent&nbsp;的一些开发,用于收集数据之类的4.得物(一面就&nbsp;oc&nbsp;了),感觉比较缺人,上海的&nbsp;uu&nbsp;可以投一投,得物社区的业务,leader&nbsp;介绍是使用&nbsp;ai&nbsp;做一些任务编排和内容分析。5.腾讯&nbsp;csig&nbsp;面试的强度比较大,都是一个半小时左右,主要拷打计算机网络和操作系统,一面两个算法题,有一道原创,技术面好评,很有水平。整体流程真是避雷😅&nbsp;三面结束,hr&nbsp;说一周内给发&nbsp;offer,然后拖了七个工作日,最后悄无声息终止流程。6.腾讯&nbsp;ieg&nbsp;捞起来一面结束后一直不更新,一面面试官约的下午五点,半小时后说自己只约了半个小时面试间,之后没消息了。7.小红书(oc&nbsp;拒了)两面技术面,mentor&nbsp;人非常非常好,面试体验也很好,感觉小红书面试官业务能力很强,氛围应该不错,如果字节没给&nbsp;offer&nbsp;的话就去小红书了。8.字节(oc&nbsp;已接),面了&nbsp;6&nbsp;次,第一次是剪映那边一面挂,第二次也是深圳的一个团队,三面挂(感觉聊的挺好,手撕也是最优解,可能存在横向),第三次是上海这边&nbsp;tiktok&nbsp;生活服务之类的,面试推进很快,一面结束两小时约二面,二面结束两小时后约&nbsp;hr&nbsp;面。9.&nbsp;还有几个&nbsp;start&nbsp;up&nbsp;也面了一下...&nbsp;...
投递Momenta等公司10个岗位
点赞 评论 收藏
分享
评论
11
43
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务