1482. 制作 m 束花所需的最少天数

1、描述

给你一个整数数组 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

来源:力扣(LeetCode)
链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2、关键字

数组,符合条件,最少,相邻,

3、思路、

1、无头绪,二分,
2、寻找二分的边界,0,到数组最大值,就是天数,特判直接不符合条件的情况,
3、搞一个辅助函数,来判断当前天数,能不能找到连续的花,构成m束花,
4、二分,while(l < r)不写等号,如果等号就无限循环了,
5、内部找结果时候,不要左右都变化,if ,else最好 l = mid + 1, r = mid;别写成l = mid + 1, r = mid - 1 ;前者虽然可能多循环一次,但是能找到正确结果,而后者不能.
6、辅助函数中,求相邻的花,时候,别搞两层循环,会时间超限,直接一遍找满足条件的情况就好了,

// 这里两层循环,时间超限
bool yesNo(vector<int>& bloomDay,int m, int k, int day){
        int n = bloomDay.size();
        int kk = k;
        int num = 0;
        for (int i = 0; i < n; i++){
            bool flag = false;
            int j;
            for( j = i; j< kk + i && j < n; j++){  // 两层循环
                if(bloomDay[j] > day){
                   
                    //i = j;
                    break;
                }
            }
            if(j == kk + i){
                num ++;
                i += k - 1;
            }
        }
        return num >= m;
    }



// 这种可以

    bool yesNo(vector<int>& bloomDay,int m, int k, int day){
        int n = bloomDay.size();
        //int kk = k;
        int flower = 0;   // 当前 束, 花的个数
        int num = 0;  // 几束花
        for (int i = 0; i < n && num <=m; i++){  // && num <=m 优化时间,如果有就直接不再找了,
           if(bloomDay[i] <= day){  // 符合条件的花
               flower++;
               if(flower == k){
                   num++;
                   flower=0;
               }
           }
           else{
               flower = 0;
           }
        }
        return num >= m;
    }

4、notes

最小也想下二分。拆分出一个辅助函数

5、复杂度

时间:O(nlogh),
n是数组长度,h是数组的最大值,遍历找最大值h,需要O(N),
二分找满足条件的需要O(logh)二分查找的迭代次数, 每次寻找能否构成花束,又是O(N),
所以O(N) + O(N logh)
空间:O(1);

6、code

class Solution {
public:
    
    bool yesNo(vector<int>& bloomDay,int m, int k, int day){
        int n = bloomDay.size();
        //int kk = k;
        int flower = 0;   // 当前 束, 花的个数
        int num = 0;  // 几束花
        for (int i = 0; i < n && num <=m; i++){  // && num <=m 优化时间,如果有就直接不再找了,
           if(bloomDay[i] <= day){  // 符合条件的花
               flower++;
               if(flower == k){
                   num++;
                   flower=0;
               }
           }
           else{
               flower = 0;
           }
        }
        return num >= m;
    }

    int minDays(vector<int>& bloomDay, int m, int k) {
        int n = bloomDay.size();
        if (n < m * k) return -1;
        int l = 0 ;
        int r = bloomDay[0];
        for(auto val : bloomDay){  // 求二分的右边界
            if(val > r){
                r = val;
            }
        }
        int res = r;
        //int mid = 0;
        while(l < r){  // 如果是带等号就无限循环了
            int mid = l + (r - l) / 2;
            if(yesNo(bloomDay,m,k,mid)){
                res = mid;
                //r = mid - 1;  // 这样写通不过
                r = mid;
            }
            else{
                l = mid + 1;
            }
        }         
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值