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
示例 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 天才能採到花來製作花束
示例 5:
輸入:bloomDay = [1,10,2,9,3,8,4,7,5,6], m = 4, k = 2
輸出:9
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/minimum-number-of-days-to-make-m-bouquets
2. 思路分析:
① 首先需要理解清楚題目,一開始的時候是沒有想到使用二分查找這個方法來解決的,後面看了一下題解才知道可以使用二分查找這個思路來解決,思路如下:因爲最大的天數是10 ^ 9 ,最小的天數是1所以我們可以取中間的天數,遍歷給出的bloomDay數組,使用一個方法來檢查數組中所有相鄰的花朵之間是否能夠構成一束,這個我們在循環中使用一個變量來記錄中間的結果即可表示是否相鄰的過程,使用另外一個變量來記錄當前構成的花有多少束,最後我們判斷出是否滿足題目中的m束花即可
② 找到一個符合條件的那麼我們就需要縮小範圍,因爲可能在mid天數的左邊可能存在更小的天數就能夠花束,這有點類似於滑動窗口的思想
③ 這道題目需要注意兩個點就好了,一個是需要懂得使用二分查找的思路,第二個是懂得使用變量來判斷或多是否相鄰並且構成的花朵是否能夠滿足m束的條件,在for循環中依次變量就通過變量的變化即可判斷是否相鄰與是否構成m束花
3. 代碼如下:
class Solution:
def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
# 注意python3在調用方法的時候需要寫在這個方法的裏面纔可以不可以寫在同一級的位置上否則會出現語法錯誤
# 下面這個方法是檢查是否相鄰
def check(bloomDay: List[int], m: int, k: int, mid: int) -> bool:
length, count = 0, 0
for i in range(len(bloomDay)):
if bloomDay[i] <= mid:
length += 1
if length == k:
length -= k
count += 1
else: length = 0
return count >= m
l, r = 1, 1000000000
res = -1
while l <= r:
mid = (l + r) // 2
if check(bloomDay, m, k, mid):
res = mid
r = mid - 1
else:
l = mid + 1
return res