携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
题目
leetcode1482. 制作 m 束花所需的最少天数
给你一个整数数组 bloomDay,以及两个整数 m 和 k 。
现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。
花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。
请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -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
题解:
这道题是二分的思想。凡是求最大,最小,最大最小,最小最大的题,一般首先想到的应该是用二分的方法,如果不行再用别的方法。
首先二分的下限就是l=0,因为最少就是需要0天,上限就是r=max(boolday[i]),就是让开花时间最长的。那么我们就在(l,r)中寻找答案。对于一个给定的天数limit,我们需要遍历数组,看看存在k个连续的开花的吗,如果是符合,那么limit应该减少,如果不符合,limit增加。直到l=r,这时的l,就是最少的天数。judge函数是判断的方法,就比较简单,昨天的一个题是用的回溯,今天直接遍历就行了。
var minDays = function(bloomDay, m, k) {
if (k * m > bloomDay.length) {
return -1;
}
let l = 1, r = Math.max(...bloomDay);
const length = bloomDay.length;
while (l < r) {
const days = Math.floor((r - l) / 2) + l;
if (canMake(bloomDay, days, m, k)) {
r = days;
} else {
l = days + 1;
}
}
return l;
};
const canMake = (bloomDay, days, m, k) => {
let bouquets = 0;
let flowers = 0;
const length = bloomDay.length;
for (let i = 0; i < length && bouquets < m; i++) {
if (bloomDay[i] <= days) {
flowers++;
if (flowers == k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
代码详解
定义二分相关的变量l、r,循环遍历判断当天的花和相邻天数的花是否可以摘取。通过辅助函数canMake来判断当天的花束的情况。