Vison's Blog
所有文章
文章总览
编辑器
Publications
About Me
Search
目录
#toc-container
下载Markdown文件
【5.9】LeetCode每日一题·制作 m 束花所需的最少天数
2021年05月09日 11时27分
标签:
LeetCode
二分
## 题目描述 给你一个整数数组 bloomDay,以及两个整数 m 和 k 。 现需要制作 m 束花。制作花束时,需要使用花园中**相邻的 k 朵花**。 花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,**恰好**可以用于**一束**花中。 请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回**-1**。 #### 示例1 ``` 输入:bloomDay = [1,10,3,10,2], m = 3, k = 1 输出:3 解释:让我们一起观察这三天的花开过程,x 表示花开,而 _ 表示花还未开。 现在需要制作 3 束花,每束只需要 1 朵。 1 天后:[x, _, _, _, _] // 只能制作 1 束花 2 天后:[x, _, _, _, x] // 只能制作 2 束花 3 天后:[x, _, x, _, x] // 可以制作 3 束花,答案为 3 ``` #### 示例2 ``` 输入:bloomDay = [1,10,3,10,2], m = 3, k = 2 输出:-1 解释:要制作 3 束花,每束需要 2 朵花,也就是一共需要 6 朵花。而花园中只有 5 朵花,无法满足制作要求,返回 -1 。 ``` #### 示例3 ``` 输入:bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3 输出:12 解释:要制作 2 束花,每束需要 3 朵。 花园在 7 天后和 12 天后的情况如下: 7 天后:[x, x, x, x, _, x, x] 可以用前 3 朵盛开的花制作第一束花。但不能使用后 3 朵盛开的花,因为它们不相邻。 12 天后:[x, x, x, x, x, x, x] 显然,我们可以用不同的方式制作两束花。 ``` #### 示例4 ``` 输入:bloomDay = [1000000000,1000000000], m = 1, k = 1 输出:1000000000 解释:需要等 1000000000 天才能采到花来制作花束 ``` #### 示例5 ``` 输入:bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2 输出:9 ``` #### 提示 ``` bloomDay.length == n 1 <= n <= 10^5 1 <= bloomDay[i] <= 10^9 1 <= m <= 10^6 1 <= k <= n ``` #### 来源 > 来源:力扣(LeetCode) > 链接:[1482. 制作 m 束花所需的最少天数 - 力扣(LeetCode)](https://leetcode-cn.com/problems/minimum-number-of-days-to-make-m-bouquets/) ## 解题思路 本题最难的一步还是读懂题意。题目的意思实际上是,第`i`朵花在`bloomDay[i]`天盛开。现在需要`m`束花,每束花`k`朵,但是限制每一束花中的所有花,是在`bloomDay`中相邻的。 由于要求最小的天数,因此方法可能为:动态规划、贪心、或者二分查找。在这里,问题的答案也满足单调性,因此对等待天数进行二分,然后判断在相应的天数,能否找到满足题目要求的`m`束花即可。 注意,可能不能摘到`m`束花,此时二分出的答案会超过右边界的最大值(即所有花中,最晚盛开的花的盛开日期),需要返回`-1`。 ## 代码 ```cpp class Solution { public: bool check(vector
& bloomDay, int mid, int m, int k){ int res = 0, cnt = 0; for(int i = 0; i < bloomDay.size(); i++){ if(bloomDay[i] <= mid){ cnt++; if(cnt == k){ res++; cnt = 0; } }else{ cnt = 0; } } return res >= m; } int minDays(vector
& bloomDay, int m, int k) { int l = 1, maxn = 0, r = 0; for(int i = 0; i < bloomDay.size(); i++){ maxn = r = max(r, bloomDay[i]); } while(l <= r){ int mid = (r-l)/2 + l; if(check(bloomDay, mid, m, k)){ r = mid - 1; }else{ l = mid + 1; } } if(l > maxn) return -1; return l; } }; ``` ## 用时和内存 > 执行用时:176 ms,在所有 C++提交中击败了78.53%的用户 > 内存消耗:61.8 MB,在所有 C++提交中击败了42.03%的用户
所有评论
暂无评论
新增评论
评论
邮箱
邮箱仅作验证使用
图形验证码
邮箱验证码
发送验证码
发表评论
所有评论
暂无评论