题目描述
给你一个整数数组 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
输入:bloomDay = [1,10,3,10,2], m = 3, k = 2
输出:-1
解释:要制作 3 束花,每束需要 2 朵花,也就是一共需要 6 朵花。
而花园中只有 5 朵花,无法满足制作要求,返回 -1。
输入: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]
显然,我们可以用不同的方式制作两束花。
输入:bloomDay = [1000000000,1000000000], m = 1, k = 1
输出:1000000000
解释:需要等 1000000000 天才能采到花来制作花束。
输入:bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2
输出:9
算法
(二分答案) $O(n \log (max - min))$
- 二分天数,然后在线性时间内判定这一天是否可以满足要求。
- 二分的上下界分别为天数的最小值以及最大值加 1。
时间复杂度
- 二分的上下界为最小值和最大值加 1,每次判定仅需要线性时间,故总时间复杂度为 $O(n \log (max - min))$。
空间复杂度
- 仅需要常数的额外空间。
C++ 代码
class Solution {
public:
bool check(const vector<int> &bloomDay, int mid, int m, int k) {
int n = bloomDay.size();
int cnt = 0;
for (int i = 0; i < n; i++) {
if (bloomDay[i] > mid) cnt = 0;
else cnt++;
if (cnt == k) {
cnt = 0;
m--;
if (m == 0)
return true;
}
}
return false;
}
int minDays(vector<int>& bloomDay, int m, int k) {
int mi = INT_MAX, ma = 0;
for (int x : bloomDay) {
mi = min(mi, x);
ma = max(ma, x);
}
int l = mi, r = ma + 1;
while (l < r) {
int mid = l + ((r - l) >> 1);
if (check(bloomDay, mid, m, k))
r = mid;
else
l = mid + 1;
}
if (l == ma + 1)
l = -1;
return l;
}
};
老哥,我还是不太明白这道题 和二分有什么关系qaq, 它不是要求满足的区别最大值吗,怎么想到二分的,
因为天数越长就会越满足,这是满足单调性的,我们要找的是符合条件中的最小值。
要求最小值,暴力做就是从最小的天数开始一天一天枚举,然后发现有二段性,线性枚举可以转成二分查找