小F的糖果工厂挑战 | 豆包MarsCode AI刷题

134 阅读4分钟

今天给大家带来的是一道:小F的糖果工厂挑战;

先来看一下题目,看看题目要我们做一些什么事情:

{415B443F-D115-499E-ADE4-D3208C66C585}.png

理解题目要求

-   工厂有n种糖果,每种糖果每天可以生产ci个。
-   需要生产a包糖果,每包糖果至少有b个。
-   我们需要计算至少需要多少天才能完成这个订单。

接着再来看一下这一道题的样例:

{F5DCA50F-F55A-4805-B56A-EC2A7CE7CAB2}.png

很好,我明白了,我管他的要多少天,我直接来一个暴力的做法,即:我们从第一天开始,逐天计算工厂能生产多少包糖果,直到满足订单要求,直接写一个O(nab)的算法复杂度不就可以了,简简单单,行了你不要讲了,我直接秒~

优缺点分析

优点:实现简单,容易理解。 

缺点:时间复杂度高,为O(nab),在数据量大时效率极低。

额。。。你的意思就是我还要优化咯。。。肯定的,你要优雅一点,比如能不能随便给你一个天数,你检查一下看看能不能达到要求。

这还不简单,我直接拿你给的天数进行计算,看看你给的这个天数可以装多少包糖果不就好了,有什么难的~

  • 这里我们先来定义一个check函数来对给定的天数进行检查:
  • cnt表示该天数可以装的糖果;
  • 计算该天数每一种糖果的数量;
  • 对每一种糖果做一个除法向下取整即可(因为每一包糖果必须是同一种,所以不够装的我们就不要了)

具体代码如下:

    public static boolean check(int n,int a,int b,int mid){
        int cnt=0;
        for(int i=0;i<n;++i){
            cnt+=arr[i]*mid/b;
        }

        return cnt>=a;
    }

接着就可以尝试用高效的算法来给定check一个天数:

二分查找优化思路

解题思路

由于暴力解法效率低下,我们可以考虑使用二分查找来优化。二分查找的核心思想是:在有序的区间内,通过不断缩小搜索范围来找到目标值。

确定搜索范围

我们知道,至少需要1天来完成订单,最多需要ab天(在最坏情况下,每天只生产一个糖果)。因此,我们的搜索范围是[1, ab]。

二分查找步骤

  1. 初始化搜索边界:l = 1r = a * b

  2. 进行二分搜索:

    • 计算中间值 mid = (l + r) / 2
    • 使用check函数检查在mid天内是否可以生产足够的糖果包。
    • 如果可以,我们需要尝试看看能不能再少一点天数,即将搜索范围缩小到左半部分,即r = mid
    • 如果不可以,我们需要尝试看看能不能稍微多一点天数,即将搜索范围缩小到右半部分,即l = mid

直到退出循环条件,即while(l+1!=r)

但是需要注意一点的是,最后r一定是可以的,但是l不一定可以(主要是我这个二分写法的不同导致的),因为假设mid一直可行,是否会出现一种l+1就是mid,而此时的mid还是可行,然后进行r=mid后,退出了循环(因为l+1==r),但是是不是l一直没有被检查是否可行,如果最后l可行,那你输出r就错误,所以我们最后还是需要check(l)一下!

到此,我们就完成了这一道题~,附上完整代码:

public class Main {
    private static int[] arr;

    public static int solution(int n, int a, int b, int[] candies) {
        // write code here
        arr=candies;
        int l=1,r=a*b;
        while(l+1<r){
            int mid=(l+r)>>1;
            if(check(n,a,b,mid)) r=mid;
            else l=mid;
        }
        
        return check(n,a,b,l) ? l:r;
    }

    public static boolean check(int n,int a,int b,int mid){
        int cnt=0;
        for(int i=0;i<n;++i){
            cnt+=arr[i]*mid/b;
        }

        return cnt>=a;
    }

    public static void main(String[] args) {
        int[] candies1 = {7, 9, 6};
        int[] candies2 = {3, 10, 8, 4};
        int[] candies3 = {1, 10};
        
        System.out.println(solution(3, 10, 20, candies1) == 10);
        System.out.println(solution(4, 5, 15, candies2) == 4);
        System.out.println(solution(2, 100, 5, candies3) == 46);
    }

}