当前位置: 首页 > article >正文

二分查找题目:制作 m 束花所需的最少天数

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:制作 m 束花所需的最少天数

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

难度

5 级

题目描述

要求

给定一个整数数组 bloomDay \texttt{bloomDay} bloomDay,以及两个整数 m \texttt{m} m k \texttt{k} k

现需要制作 m \texttt{m} m 束花。制作花束时,需要使用花园中相邻的 k \texttt{k} k 朵花

花园中有 n \texttt{n} n 朵花,第 i \texttt{i} i 朵花会在第 bloomDay[i] \texttt{bloomDay[i]} bloomDay[i] 天盛开,恰好可以用于一束花中。

返回从花园中制作 m \texttt{m} m 束花需要等待的最少的天数。如果不能制作 m \texttt{m} m 束花则返回 -1 \texttt{-1} -1

示例

示例 1:

输入: bloomDay   =   [1,10,3,10,2],   m   =   3,   k   =   1 \texttt{bloomDay = [1,10,3,10,2], m = 3, k = 1} bloomDay = [1,10,3,10,2], m = 3, k = 1
输出: 3 \texttt{3} 3
解释:以下是前三天的花开过程, x \texttt{x} x 表示花开,而 _ \texttt{\_} _ 表示花还未开。
现在需要制作 3 \texttt{3} 3 束花,每束需要 1 \texttt{1} 1 朵花。
1 \texttt{1} 1 天后: [x,   _,   _,   _,   _] \texttt{[x, \_, \_, \_, \_]} [x, _, _, _, _] // 只能制作 1 \texttt{1} 1 束花。
2 \texttt{2} 2 天后: [x,   _,   _,   _,   x] \texttt{[x, \_, \_, \_, x]} [x, _, _, _, x] // 只能制作 2 \texttt{2} 2 束花。
3 \texttt{3} 3 天后: [x,   _,   x,   _,   x] \texttt{[x, \_, x, \_, x]} [x, _, x, _, x] // 可以制作 3 \texttt{3} 3 束花,答案为 3 \texttt{3} 3

示例 2:

输入: bloomDay   =   [1,10,3,10,2],   m   =   3,   k   =   2 \texttt{bloomDay = [1,10,3,10,2], m = 3, k = 2} bloomDay = [1,10,3,10,2], m = 3, k = 2
输出: -1 \texttt{-1} -1
解释:要制作 3 \texttt{3} 3 束花,每束需要 2 \texttt{2} 2 朵花,因此一共需要 6 \texttt{6} 6 朵花。而花园中只有 5 \texttt{5} 5 朵花,无法满足制作要求,返回 -1 \texttt{-1} -1

示例 3:

输入: bloomDay   =   [7,7,7,7,12,7,7],   m   =   2,   k   =   3 \texttt{bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3} bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3
输出: 12 \texttt{12} 12
解释:要制作 2 \texttt{2} 2 束花,每束需要 3 \texttt{3} 3 朵花。
花园在 7 \texttt{7} 7 天后和 12 \texttt{12} 12 天后的情况如下:
7 \texttt{7} 7 天后: [x,   x,   x,   x,   _,   x,   x] \texttt{[x, x, x, x, \_, x, x]} [x, x, x, x, _, x, x]
可以用前 3 \texttt{3} 3 朵盛开的花制作第一束花。但不能使用后 3 \texttt{3} 3 朵盛开的花,因为它们不相邻。
12 \texttt{12} 12 天后: [x,   x,   x,   x,   x,   x,   x] \texttt{[x, x, x, x, x, x, x]} [x, x, x, x, x, x, x]
显然,我们可以用不同的方式制作两束花。

数据范围

  • bloomDay.length = n \texttt{bloomDay.length} = \texttt{n} bloomDay.length=n
  • 1 ≤ n ≤ 10 5 \texttt{1} \le \texttt{n} \le \texttt{10}^\texttt{5} 1n105
  • 1 ≤ bloomDay[i] ≤ 10 9 \texttt{1} \le \texttt{bloomDay[i]} \le \texttt{10}^\texttt{9} 1bloomDay[i]109
  • 1 ≤ m ≤ 10 6 \texttt{1} \le \texttt{m} \le \texttt{10}^\texttt{6} 1m106
  • 1 ≤ k ≤ n \texttt{1} \le \texttt{k} \le \texttt{n} 1kn

解法

思路和算法

为了制作 m m m 束花,每束需要 k k k 朵花,共需要 m × k m \times k m×k 朵花。花园中有 n n n 朵花,如果 m × k > n m \times k > n m×k>n,则即使将全部 n n n 朵花都用于制作花束也无法满足制作要求,因此返回 − 1 -1 1

m × k ≤ n m \times k \le n m×kn 时,制作全部花束需要的花不超过 n n n 朵,因此当所有花都盛开时,一定可以制作全部花束。

如果等待天数大于等于最少天数,则可以制作全部花束;如果等待天数小于最少天数,则不能制作全部花束。因此,这道题是二分查找判定问题,需要找到最少天数。

low \textit{low} low high \textit{high} high 分别表示二分查找的下界和上界。由于 m m m k k k 都至少是 1 1 1,且每朵花盛开的天数都至少是 1 1 1 天,因此 low \textit{low} low 的初始值等于 1 1 1;由于当所有花都盛开时一定可以制作全部花束,因此 high \textit{high} high 的初始值等于 bloomDay \textit{bloomDay} bloomDay 中的最大值。

当等待天数是 days \textit{days} days 时, bloomDay \textit{bloomDay} bloomDay 中的小于等于 days \textit{days} days 的元素对应的花已经盛开, bloomDay \textit{bloomDay} bloomDay 中的大于 days \textit{days} days 的元素对应的花尚未盛开。由此可以得到每朵花是否盛开,并根据连续盛开的花朵数计算可以制作多少束花。

每次查找时,取 mid \textit{mid} mid low \textit{low} low high \textit{high} high 的平均数向下取整,将 mid \textit{mid} mid 作为等待天数,判断是否可以制作全部花束,执行如下操作。

  • 如果等待天数是 mid \textit{mid} mid 时可以制作全部花束,则最少天数小于等于 mid \textit{mid} mid,因此在 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 中继续查找。

  • 如果等待天数是 mid \textit{mid} mid 时不能制作全部花束,则最少天数大于 mid \textit{mid} mid,因此在 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 中继续查找。

low = high \textit{low} = \textit{high} low=high 时,查找结束,此时 low \textit{low} low 即为最少天数。

代码

class Solution {
    public int minDays(int[] bloomDay, int m, int k) {
        if ((long) m * k > bloomDay.length) {
            return -1;
        }
        int low = Arrays.stream(bloomDay).min().getAsInt(), high = Arrays.stream(bloomDay).max().getAsInt();
        while (low < high) {
            int mid = low + (high - low) / 2;
            if (canMakeMBouquets(bloomDay, m, k, mid)) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return low;
    }

    public boolean canMakeMBouquets(int[] bloomDay, int m, int k, int days) {
        int bouquets = 0;
        int consecutive = 0;
        int n = bloomDay.length;
        for (int i = 0; i < n; i++) {
            if (bloomDay[i] <= days) {
                consecutive++;
                if (consecutive % k == 0) {
                    bouquets++;
                    if (bouquets == m) {
                        return true;
                    }
                }
            } else {
                consecutive = 0;
            }
        }
        return false;
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ m ) O(n \log m) O(nlogm),其中 n n n 是数组 bloomDay \textit{bloomDay} bloomDay 的长度, m m m 是数组 bloomDay \textit{bloomDay} bloomDay 中的最大值。需要执行 O ( log ⁡ m ) O(\log m) O(logm) 次二分查找,每次二分查找需要 O ( n ) O(n) O(n) 的时间遍历数组 bloomDay \textit{bloomDay} bloomDay 判断是否可以制作全部花束,时间复杂度是 O ( n log ⁡ m ) O(n \log m) O(nlogm)

  • 空间复杂度: O ( 1 ) O(1) O(1)


http://www.kler.cn/a/443686.html

相关文章:

  • |-牛式-|
  • C++ Learning string类的使用
  • 一体式IO模块:打印机加工产线国产化降本增效的新利器
  • Chromium 中chrome.webRequest扩展接口定义c++
  • 基于Matlab实现无刷直流电机仿真
  • CSPM认证最推荐学习哪个级别?
  • Qt WORD/PDF(三)使用 QAxObject 对 Word 替换(QML)
  • Nginx常用配置详解(1)
  • upload-labs靶场1-19关
  • 【信息系统项目管理师-论文真题】2017下半年论文详解(包括解题思路和写作要点)
  • AUTOSAR OS 中Alarm 和 Event 本质和应用
  • 【WebRTC】视频发送链路中类的简单分析(上)
  • 【Golang】 Go 语言中的 Struct、JSON 和 Map 互转:详细指南
  • CTF知识集-PHP特性
  • NFTScan | 12.09~12.15 NFT 市场热点汇总
  • [NSSCTF 2022 Spring Recruit]factor
  • 对于给定PI参数的锁相环带宽简单计算方法
  • REST模式是什么,以及其他架构风格
  • 大模型中RAG模型的检索过程是如何实现的?(附最佳实践资料)
  • 唯品会C++面试题及参考答案
  • 设计模式-行为型模式
  • 企业如何通过TDSQL实现高效数据库迁移与性能优化
  • windows使用python写的YOLO来实现目标识别
  • CRC校验例题详解
  • 页面无滚动条,里面div各自有滚动条
  • Redis 7.x哨兵模式如何实现?基于Spring Boot 3.x版