Minimum Days to Make M Bouquets
Problem and examples
You are given an array bloomDay[] where bloomDay[i] represents the day on which the i-th flower will bloom. Your task is to determine the minimum number of days required to make m bouquets, where each bouquet requires k adjacent bloomed flowers.
- You can only use a flower if it has bloomed on or before the day you're checking.
- You must use exactly
kadjacent flowers to make each bouquet.
If it's not possible to make m bouquets, return -1.
| Bloom Day Array | m | k | Output | Description |
|---|---|---|---|---|
| [1, 10, 3, 10, 2] | 3 | 1 | 3 | On day 3, flowers at indices 0, 2, and 4 are bloomed. 3 bouquets possible. |
| [1, 10, 3, 10, 2] | 3 | 2 | -1 | Not enough adjacent flowers to form 3 bouquets of 2 flowers. |
| [7, 7, 7, 7, 12, 7, 7] | 2 | 3 | 12 | Day 12 is the earliest when two bouquets of 3 adjacent flowers can be made. |
| [1000000000, 1000000000] | 1 | 1 | 1000000000 | Only one flower needed, take the earliest available. |
| [1, 10, 2, 9, 3, 8] | 2 | 2 | 9 | Day 9 gives two pairs of adjacent bloomed flowers: (2,3) and (4,5) |
| [1] | 1 | 1 | 1 | One flower, one bouquet needed — return 1. |
| [1] | 2 | 1 | -1 | Only one flower, but two bouquets required — not possible. |
| [] | 1 | 1 | -1 | Empty array — can't make any bouquets. |
Explore Minimum Days to Make M Bouquets
Load an example or enter your own input. Use the player controls to follow each change.
Understanding the Problem
We are given an array of integers where each element represents the day a flower will bloom. Our task is to make m bouquets, each consisting of exactly k adjacent bloomed flowers. A flower can only be used on or after the day it blooms.
The main question is: What is the minimum number of days needed to make m such bouquets?
Step-by-Step Solution with Example
Step 1: Think About a Single Day
Let’s say we choose a day, like day 7. On this day, only flowers that bloom on or before day 7 can be used. We scan the array and try to form bouquets using only these bloomed flowers. We can only form a bouquet if we find k adjacent bloomed flowers.
Step 2: Try to Simulate It
Let’s take an example:
flowers = [1, 10, 3, 10, 2], m = 1, k = 2
This means we need to make 1 bouquet using 2 adjacent bloomed flowers. On day 3, the bloom status is:
- Day 1 → bloomed (1 ≤ 3)
- Day 10 → not bloomed (10 > 3)
- Day 3 → bloomed (3 ≤ 3)
- Day 10 → not bloomed
- Day 2 → bloomed (2 ≤ 3)
The bloomed flowers are at index 0, 2, and 4. None of them are adjacent, so we cannot form any bouquet on day 3. Try day 10 — now all flowers are bloomed, and we can form a bouquet with [3, 10] or [10, 2]. So day 10 works. We try to find the minimum such day.
Step 3: Use Binary Search to Optimize
Since trying all days linearly is slow, we use binary search on days from the minimum to the maximum bloom value.
At each mid-point day, we check if it's possible to make m bouquets. If it is, we try a smaller day. If it’s not, we try a bigger day. This helps us zero in on the minimum valid day efficiently.
Step 4: Bouquet Formation Check Logic
While scanning, we count how many adjacent bloomed flowers we have. If a flower is bloomed on or before the current day, we increase the count. If not, we reset the count to 0. Every time the count reaches k, we form a bouquet and reset the count.
Edge Cases
- Not Enough Flowers: If
m × kis greater than the total number of flowers, it's impossible to form the required bouquets. We should return-1immediately. - All Flowers Bloom Late: Even if all flowers bloom on high days (like day 1000), binary search will still find the answer quickly.
- Empty Array: If the array is empty, we cannot form any bouquet. Return
-1. - Exactly Enough Flowers: If the array has exactly
m × kflowers, we must use every flower — and they must be arranged in proper adjacent groups. This is a tight case to test our adjacency logic.
Finally
We solved this problem using a binary search approach, which significantly improves performance over a brute force solution. The key insights were:
- Understanding how to simulate bouquet formation on a specific day
- Applying binary search on the range of days to minimize the answer
- Carefully handling edge cases, especially when adjacency is required
The time complexity is O(n × log(max bloom day)), where n is the number of flowers. This makes the solution both fast and scalable.
- Set
low= minimum bloom day,high= maximum bloom day. - Perform binary search while
low ≤ high. - Set
mid = (low + high) / 2. - Check if it’s possible to make
mbouquets inmiddays using a helper function: - Traverse bloom days. Count consecutive bloomed roses (i.e.,
arr[i] ≤ mid). - Every time you collect
kadjacent, increment bouquet count and reset count. - If bouquet count ≥ m, return true.
- If possible, store
midas answer and movehigh = mid - 1. - Else move
low = mid + 1.
Implementation and efficiency
C implementation
#include <stdio.h>
int canMakeBouquets(int bloomDay[], int n, int m, int k, int day) {
int bouquets = 0, flowers = 0;
for (int i = 0; i < n; i++) {
if (bloomDay[i] <= day) {
flowers++;
if (flowers == k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
int minDays(int bloomDay[], int n, int m, int k) {
if ((long)m * k > n) return -1;
int low = 1e9, high = 0, ans = -1;
for (int i = 0; i < n; i++) {
if (bloomDay[i] < low) low = bloomDay[i];
if (bloomDay[i] > high) high = bloomDay[i];
}
while (low <= high) {
int mid = low + (high - low) / 2;
if (canMakeBouquets(bloomDay, n, m, k, mid)) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return ans;
}
int main() {
int bloom[] = {1, 10, 3, 10, 2};
int m = 3, k = 1;
printf("Minimum Days: %d\n", minDays(bloom, 5, m, k));
return 0;
}C++ implementation
#include <iostream>
#include <vector>
using namespace std;
bool canMakeBouquets(vector<int>& bloomDay, int m, int k, int day) {
int bouquets = 0, flowers = 0;
for (int b : bloomDay) {
if (b <= day) {
flowers++;
if (flowers == k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
int minDays(vector<int>& bloomDay, int m, int k) {
if ((long)m * k > bloomDay.size()) return -1;
int low = *min_element(bloomDay.begin(), bloomDay.end());
int high = *max_element(bloomDay.begin(), bloomDay.end());
int ans = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (canMakeBouquets(bloomDay, m, k, mid)) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return ans;
}
int main() {
vector<int> bloom = {1, 10, 3, 10, 2};
cout << "Minimum Days: " << minDays(bloom, 3, 1) << endl;
return 0;
}Python implementation
def can_make_bouquets(bloom_day, m, k, day):
bouquets = flowers = 0
for b in bloom_day:
if b <= day:
flowers += 1
if flowers == k:
bouquets += 1
flowers = 0
else:
flowers = 0
return bouquets >= m
def min_days(bloom_day, m, k):
if m * k > len(bloom_day):
return -1
low, high = min(bloom_day), max(bloom_day)
ans = -1
while low <= high:
mid = (low + high) // 2
if can_make_bouquets(bloom_day, m, k, mid):
ans = mid
high = mid - 1
else:
low = mid + 1
return ans
bloom = [1, 10, 3, 10, 2]
m, k = 3, 1
print("Minimum Days:", min_days(bloom, m, k))Java implementation
public class Bouquets {
public static boolean canMakeBouquets(int[] bloomDay, int m, int k, int day) {
int bouquets = 0, flowers = 0;
for (int b : bloomDay) {
if (b <= day) {
flowers++;
if (flowers == k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
public static int minDays(int[] bloomDay, int m, int k) {
if ((long)m * k > bloomDay.length) return -1;
int low = Integer.MAX_VALUE, high = Integer.MIN_VALUE;
for (int day : bloomDay) {
low = Math.min(low, day);
high = Math.max(high, day);
}
int ans = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (canMakeBouquets(bloomDay, m, k, mid)) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return ans;
}
public static void main(String[] args) {
int[] bloom = {1, 10, 3, 10, 2};
int m = 3, k = 1;
System.out.println("Minimum Days: " + minDays(bloom, m, k));
}
}JavaScript implementation
function canMakeBouquets(bloomDay, m, k, day) {
let bouquets = 0, flowers = 0;
for (let b of bloomDay) {
if (b <= day) {
flowers++;
if (flowers === k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
function minDays(bloomDay, m, k) {
if (m * k > bloomDay.length) return -1;
let low = Math.min(...bloomDay), high = Math.max(...bloomDay);
let ans = -1;
while (low <= high) {
let mid = Math.floor((low + high) / 2);
if (canMakeBouquets(bloomDay, m, k, mid)) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return ans;
}
const bloom = [1, 10, 3, 10, 2];
console.log("Minimum Days:", minDays(bloom, 3, 1));Go implementation
package main
import (
"fmt"
)
func canMakeBouquets(bloomDay []int, m, k, day int) bool {
bouquets, flowers := 0, 0
for _, b := range bloomDay {
if b <= day {
flowers++
if flowers == k {
bouquets++
flowers = 0
}
} else {
flowers = 0
}
}
return bouquets >= m
}
func minDays(bloomDay []int, m, k int) int {
if m*k > len(bloomDay) {
return -1
}
low, high := bloomDay[0], bloomDay[0]
for _, day := range bloomDay {
if day < low {
low = day
}
if day > high {
high = day
}
}
ans := -1
for low <= high {
mid := (low + high) / 2
if canMakeBouquets(bloomDay, m, k, mid) {
ans = mid
high = mid - 1
} else {
low = mid + 1
}
}
return ans
}
func main() {
bloom := []int{1, 10, 3, 10, 2}
m, k := 3, 1
fmt.Println("Minimum Days:", minDays(bloom, m, k))
}Rust implementation
fn can_make_bouquets(bloom_day: &Vec<i32>, m: i32, k: i32, day: i32) -> bool {
let mut bouquets = 0;
let mut flowers = 0;
for &b in bloom_day.iter() {
if b <= day {
flowers += 1;
if flowers == k {
bouquets += 1;
flowers = 0;
}
} else {
flowers = 0;
}
}
bouquets >= m
}
fn min_days(bloom_day: Vec<i32>, m: i32, k: i32) -> i32 {
if m * k > bloom_day.len() as i32 {
return -1;
}
let mut low = *bloom_day.iter().min().unwrap();
let mut high = *bloom_day.iter().max().unwrap();
let mut ans = -1;
while low <= high {
let mid = (low + high) / 2;
if can_make_bouquets(&bloom_day, m, k, mid) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
ans
}
fn main() {
let bloom = vec![1, 10, 3, 10, 2];
let m = 3;
let k = 1;
println!("Minimum Days: {}", min_days(bloom, m, k));
}Kotlin implementation
fun canMakeBouquets(bloomDay: IntArray, m: Int, k: Int, day: Int): Boolean {
var bouquets = 0
var flowers = 0
for (b in bloomDay) {
if (b <= day) {
flowers++
if (flowers == k) {
bouquets++
flowers = 0
}
} else {
flowers = 0
}
}
return bouquets >= m
}
fun minDays(bloomDay: IntArray, m: Int, k: Int): Int {
if (m.toLong() * k > bloomDay.size) return -1
var low = bloomDay.minOrNull()!!
var high = bloomDay.maxOrNull()!!
var ans = -1
while (low <= high) {
val mid = low + (high - low) / 2
if (canMakeBouquets(bloomDay, m, k, mid)) {
ans = mid
high = mid - 1
} else {
low = mid + 1
}
}
return ans
}
fun main() {
val bloom = intArrayOf(1, 10, 3, 10, 2)
println("Minimum Days: ${minDays(bloom, 3, 1)}")
}TypeScript implementation
function canMakeBouquets(bloomDay: number[], m: number, k: number, day: number): boolean {
let bouquets = 0, flowers = 0;
for (let b of bloomDay) {
if (b <= day) {
flowers++;
if (flowers === k) {
bouquets++;
flowers = 0;
}
} else {
flowers = 0;
}
}
return bouquets >= m;
}
function minDays(bloomDay: number[], m: number, k: number): number {
if (m * k > bloomDay.length) return -1;
let low = Math.min(...bloomDay), high = Math.max(...bloomDay);
let ans = -1;
while (low <= high) {
const mid = Math.floor((low + high) / 2);
if (canMakeBouquets(bloomDay, m, k, mid)) {
ans = mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return ans;
}
const bloom = [1, 10, 3, 10, 2];
console.log("Minimum Days:", minDays(bloom, 3, 1));Time complexity
| Case | Time | Explanation |
|---|---|---|
| best case | O(n) | In the best case, the first binary search guess gives a valid answer after a single bouquet check. |
| average case | O(n log(max_day - min_day)) | Binary search runs in log(max_day - min_day) steps and each step checks the full array to count bouquets. |
| worst case | O(n log(max_day - min_day)) | Binary search iterates across the entire range of possible days, checking all n roses each time. |
Space complexity
O(1)
Only a few variables are used; no extra space is needed apart from input.