力扣【二分查找】:1482. 制作 m 束花所需的最少天数
题目描述:
给你一个整数数组 bloomDay,以及两个整数 m 和 k 。
现需要制作 m 束花。制作花束时,需要使用花园中 相邻的 k 朵花 。
花园中有 n 朵花,第 i 朵花会在 bloomDay[i] 时盛开,恰好 可以用于 一束 花中。
请你返回从花园中摘 m 束花需要等待的最少的天数。如果不能摘到 m 束花则返回 -1 。
算法思路:
- 题目要求制作的花束需要用相邻的k朵花,所以不能修改bloomDay的顺序。当等待的天数增加时,成熟的花必然更多,因此可以制作的花束的数量只会增加而不会减少,只要写出在特定天数下能够获得的花束数量的函数就可以遍历所有可能的天数从而找出满足要求的最少的天数。
- 可能的天数最小值为1,而最大值为成熟时间最长的花所需时间,即数组最大值,很显然这个数值区间可以通过二分查找的方式降低时间复杂度。
- 所有题目的核心难点就是如何编写指定天数可以得到的花束的函数,由于只能采用相邻的花制作花束,这里通过遍历数组的方式记录可以获得的花束数量。
- 显然如果一朵花成熟就可以将它收入当前的花束中,我们可以定义一个遍历记录当前花束中的花朵数量,又因为每次花朵数量最多增加1,花朵数量不会跳过k,只需要在花朵数量等于k时重置花朵数量并对花束数量加一即可,而如果花未成熟,此时花朵数量一定小于k,因为我们是在花朵数加一后对花朵数做判断,而且花朵加一仅在花成熟时执行,所有如果花朵未成熟则只需要将花朵数量置零即可,意味着之前收集的花朵不会用于制作花束。
代码:
时间复杂度:设二分区间大小为m,数组长为n,每次二分查找都需要遍历一次数组,O(n log (m))
空间复杂度:O(1)
class Solution {
public:
int minDays(vector<int>& bloomDay, int m, int k) {
int lower_day = 1, upper_day = *std::max_element(bloomDay.begin(), bloomDay.end());
while (lower_day < upper_day) {
int day_count = lower_day + (upper_day - lower_day) / 2;
int bunchs = GetBunchs(bloomDay, k, day_count);
if (bunchs < m) {
lower_day = day_count + 1;
} else {
upper_day = day_count;
}
}
if (GetBunchs(bloomDay, k, upper_day) < m) {
return -1;
}
return upper_day;
}
int GetBunchs(std::vector<int> &bloomDay, int k, int day_count) {
int bunch_count = 0;
int flower_count = 0;
for (const int &day : bloomDay) {
if (day <= day_count) {
++flower_count;
if (flower_count == k) {
flower_count = 0;
++bunch_count;
}
} else {
flower_count = 0;
}
}
return bunch_count;
}
};
浙公网安备 33010602011771号