Leetcode 1482: 制作 m 束花所需的最少天数 Minimum Number of Days to Make m Bouquets

中文描述:

给你一个整数数组 bloomDay,以及两个整数 m 和 k 。
现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。
花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。
请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。

题目描述:

Given an integer array bloomDay, an integer m and an integer k.
We need to make m bouquets. To make a bouquet, you need to use k adjacent flowers from the garden.
The garden consists of n flowers, the ith flower will bloom in the bloomDay[i] and then can be used in exactly one bouquet.
Return the minimum number of days you need to wait to be able to make m bouquets from the garden. If it is impossible to make m bouquets return -1.

Example 1:

Input: bloomDay = [1,10,3,10,2], m = 3, k = 1
Output: 3
Explanation: Let’s see what happened in the first three days. x means flower bloomed and _ means flower didn’t bloom in the garden.
We need 3 bouquets each should contain 1 flower.
After day 1: [x, _, _, _, _] // we can only make one bouquet.
After day 2: [x, _, _, _, x] // we can only make two bouquets.
After day 3: [x, _, x, _, x] // we can make 3 bouquets. The answer is 3.

Example 2:

Input: bloomDay = [1,10,3,10,2], m = 3, k = 2
Output: -1
Explanation: We need 3 bouquets each has 2 flowers, that means we need 6 flowers. We only have 5 flowers so it is impossible to get the needed bouquets and we return -1.

Example 3:

Input: bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3
Output: 12
Explanation: We need 2 bouquets each should have 3 flowers.
Here’s the garden after the 7 and 12 days:
After day 7: [x, x, x, x, _, x, x]
We can make one bouquet of the first three flowers that bloomed. We cannot make another bouquet from the last three flowers that bloomed because they are not adjacent.
After day 12: [x, x, x, x, x, x, x]
It is obvious that we can make two bouquets in different ways.

Example 4:

Input: bloomDay = [1000000000,1000000000], m = 1, k = 1
Output: 1000000000
Explanation: You need to wait 1000000000 days to have a flower ready for a bouquet.
Example 5:
Input: bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2
Output: 9

Constraints:

bloomDay.length == n
1 <= n <= 105
1 <= bloomDay[i] <= 109
1 <= m <= 106
1 <= k <= n

Time complexity: O O O( N N Nlog(W)), where N is the number of piles, and W is the maximum size of a pile.
Space complexity: O O O( 1 1 1)
二分 二分搜索总结
根据上面的二分搜索总结,注意此题为找最少的天数 使得可以从花园中摘 m 束花。
则此题可以归纳为二分找左边界(最优区间的左边) 套用基础模版:
初始化左边界 lo:1。
初始化右边界 hi:最长的等待天数(数组中最大的数)。
循环条件: lo < hi
中间位置 mid = lo + (hi-lo>>1),
更新左边界 lo = mid+1,
更新右边界 hi = mid,
左右边界的判断条件:
注意更新左右边界的判断条件当我们给定一个值 day代表采摘天数,我们可以线性地验证是否存在一种方案,当采摘天数为 day时, 我们可以至少摘m束花。

贪心地模拟分割的过程,从前到后遍历数组,用 sum 表示当前成功才找的花束的值,adj 表示当前花朵的数量。当 当前的开花等待天数天数 <= day 时表示 这朵花可以摘,adj ++ ,当 adj == k 时界这一束花成功则 sum++,否则 > day时表示此花朵不能摘 则更新 adj = 0。 遍历结束后验证是否 sum >= m。

满足此条件的话则我们在 [lo, x(mid)] 的 范围内继续寻找是否存在更小的 x 值满足此条件 即 hi = mid。反之则表示给定的 天数day值过小 lo = mid + 1.

class Solution {
    public int minDays(int[] bloomDay, int m, int k) {
        if(m*k > bloomDay.length) return -1;
        int l = m;
        int h = 0;
        int mid;
        for(int i:bloomDay){
            h = Math.max(h, i);
        }
        
        while(l < h){
           mid = l +(h-l>>1);
            if(check(bloomDay, m, k, mid)){
                h = mid;
            }else{
                l = mid+1;
            }
        }
        return l;
    }
    
    private boolean check(int[] bloomDay, int m, int k, int day){
        int sum = 0;
        int adj = 0;
        for(int i:bloomDay){
            if(i <= day){
                adj++;
                if(adj == k){
                    sum++;
                    adj = 0;
                }
            }else{
                adj = 0;
            }
        }
        return sum >= m;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值