《LeetCode之每日一题》:24. 制作 m 束花所需的最少天数
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:24. 制作 m 束花所需的最少天数相关的知识,希望对你有一定的参考价值。
题目链接: 制作 m 束花所需的最少天数
有关题目
给你一个整数数组 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 天才能采到花来制作花束
提示:
bloomDay.length == n
1 <= n <= 10^5
1 <= bloomDay[i] <= 10^9
1 <= m <= 10^6
1 <= k <= n
题解
法一:二分查找
思路:
1、判断能够制作花束基本条件
2、找出bloomDay中的最大元素,即所需时间最长的花
3、构造辅助函数canMake--作用:判断在给定的天数内能否制作出指定数量的花束,可以return true;反之false
4、根据二分查找特殊性,逼近所需最小天数
详细见官方链接
class Solution {
public:
int minDays(vector<int>& bloomDay, int m, int k) {
if (m > (bloomDay.size() / k))//防止溢出我们用除
return -1;
int low = 1, high = 1;
for (int i = 0; i < bloomDay.size(); i++)
high = max(high,bloomDay[i]);
while(low < high)
{
int days = (high - low) / 2 + low;
if (canMake(bloomDay,m,k,days))//days随着二分查找的进行从大到小慢慢逼近最少天数,刚开始肯定是能找到某一天数,只不过不是最小而已罢了
high = days;
else
low = days + 1;
//我们low记录的最终目的为逼近最少需要制作花的天数,随着二分查找
}
return low;
}
bool canMake(vector<int> &bloomDay,int m,int k, int days)
{
int flowers = 0;
int bouquets = 0;//定义花束
int length = bloomDay.size();
for (int i = 0; i < length && bouquets < m; i++)
{
//这边就是限制连续的子数组,满足就进行
if (bloomDay[i] <= days)
{
flowers++;
if (flowers == k)
{
bouquets++;
flowers = 0;
}
}
else //不满足条件就将前面的花朵置零,因为不连续,即不相邻了
{
flowers = 0;
}
}
return bouquets >= m;
}
};
时间复杂度:O(nlogh)
n为数组的的长度,h为数组中最大元素,先遍历找到最大元素,最坏需要O(n)次
接下俩的二分迭代次数,所需O(logh)次,要判断是否可以组成花束所需O(n),因此所需时间复杂度O(nlogh)
结合函数函数的单调性,故总的时间复杂度为O(nlogh)
空间复杂度:O(1)
C版本
int canMake(int* bloomDay, int bloomDaySize,int m, int k,int days)
{
int flowers = 0;
int bouquets = 0;
int length = bloomDaySize;
for (int i = 0; i < length && bouquets < m; i++)
{
if (bloomDay[i] <= days)
{
flowers++;
if (flowers == k)
{
bouquets++;
flowers = 0;
}
}
else
{
flowers = 0;
}
}
return bouquets >= m;
}
int minDays(int* bloomDay, int bloomDaySize, int m, int k){
if (m > (bloomDaySize / k))
return -1;
int low = 1, high = 1;
for (int i = 0; i < bloomDaySize; i++)
{
high = fmax(high,bloomDay[i]);
}
while (low < high)
{
int days = (high - low) / 2 + low;
if (canMake(bloomDay,bloomDaySize,m,k,days))
high = days;
else
low = days + 1;
}
return low;
}
以上是关于《LeetCode之每日一题》:24. 制作 m 束花所需的最少天数的主要内容,如果未能解决你的问题,请参考以下文章