题目
思路
首先我们需要检查总的花朵数量是否足够制作花束,如果不够则直接返回-1
。
在花朵够的情况下,最大的等待天数max_day
是所有花的开放的天数(max(bloomDay)
),最少等待的天数min_day
是第一朵花开放的天数(min(bloomDay)
)。然后我们需要确定在第d
天时(
d
∈
[
m
i
n
_
d
a
y
,
m
a
x
d
a
y
]
d \in [min\_day, max_day]
d∈[min_day,maxday]),开放的花是否足够制作所需的花束,判断过程较为简单,我们使用一个变量f
记录连续开放的花数量,顺序扫描bloomDay
,当bloomDay[i] <= d
时表示该花已经开放,我们将连续开放的花数量f
加1,否则,则设置f
为0
(当前连续的花朵不够制作一个花束)。当f == k
时表示已经有足够的花制作一个花束,我们将m
减去1 ,并重新设置f
为0以搜索下一个足够制作花束的连续花朵。最终如果m > 0
表示无法制作足够的花束,否则表示可以制作足够的花束。
我们可以从min_day
开始逐个测试,直到刚好能够满足制作所有花束的天数即为最少天数,不过更快的方式是使用二分搜索来确定最少天数。对于正确答案所处的范围[min_day, max_day]
,如果其中的一个值d
不满足需求,那么正确答案必然>d
,因此正确答案的范围是 [d+1, max_day]
,如果d
满足需求,那么可能更小的d
也满足需求,即正确答案<=d
,因此正确答案的范围是[min_day, d]
。直到正确答案只包含一个值时,就是最终的答案。
代码
class Solution {
public:
int minDays(vector<int>& bloomDay, int m, int k) {
if(bloomDay.size() < (m * k)) {
return -1;
}
int min_day = INT_MAX;
int max_day = INT_MIN;
for(int n:bloomDay) {
if (n > max_day) {
max_day = n;
}
if (n < min_day) {
min_day = n;
}
}
int day = (min_day + max_day) / 2;
while(min_day != max_day) {
if (check(bloomDay, m, k, day) == false) {
min_day = day + 1;
} else {
max_day = day;
}
day = (min_day + max_day) / 2;
}
return day;
}
bool check(vector<int>& bloomDay, int m, int k, int day) {
int flower = 0;
for(int n: bloomDay) {
if (n <= day) {
flower++;
} else {
flower=0;
}
if (flower == k) {
m--;
if (m == 0) {
break;
}
flower = 0;
}
}
return (m > 0)? false : true;
}
};