1482. Minimum Number of Days to Make m Bouquets
Problem Description
You have a garden with n flowers arranged in a row. Each flower blooms on a specific day given by the array bloomDay, where bloomDay[i] represents the day when the i-th flower will bloom.
Your goal is to make m bouquets, where each bouquet requires exactly k adjacent flowers that have already bloomed. Once a flower is used in a bouquet, it cannot be used in another bouquet.
The problem asks you to find the minimum number of days you need to wait before you can make m bouquets. If it's impossible to make m bouquets (for example, if there aren't enough flowers total, i.e., n < m * k), return -1.
Key constraints:
- Flowers must be adjacent (consecutive) in the garden to form a bouquet
- Each flower can only be used in one bouquet
- A flower can only be used after it has bloomed (on or after day
bloomDay[i])
Example scenario:
If bloomDay = [1, 10, 3, 10, 2], m = 3, and k = 1:
- On day 1: flower at index 0 blooms
- On day 2: flowers at indices 0 and 4 have bloomed
- On day 3: flowers at indices 0, 2, and 4 have bloomed (3 flowers total, can make 3 bouquets of size 1)
- Answer: 3 days
If bloomDay = [1, 10, 3, 10, 2], m = 3, and k = 2:
- We need 3 bouquets with 2 adjacent flowers each (6 flowers total)
- We only have 5 flowers, so it's impossible
- Answer: -1
Intuition
The key insight is recognizing that this problem has a monotonic property: if we can make m bouquets by day t, then we can definitely make m bouquets on any day after t (since more flowers will have bloomed). Conversely, if we cannot make m bouquets by day t, we cannot make them on any day before t either.
This monotonic property immediately suggests binary search on the answer. Instead of checking every possible day sequentially, we can search for the minimum day efficiently.
Think of it this way: imagine we have a timeline from day 1 to the maximum bloom day. At some point on this timeline, we transition from "cannot make m bouquets" to "can make m bouquets". We want to find that exact transition point.
For any given day d, we can check if it's possible to make m bouquets by:
- Looking at which flowers have bloomed by day
d(those withbloomDay[i] <= d) - Counting how many groups of
kconsecutive bloomed flowers we can find - Checking if we have at least
msuch groups
The checking process works like a sliding window: we traverse the array and count consecutive bloomed flowers. When we reach k consecutive bloomed flowers, we've found one bouquet and reset our counter. If we encounter a flower that hasn't bloomed yet, we reset the counter since the consecutive sequence is broken.
The search space for our binary search is from day 1 to the maximum value in bloomDay (since all flowers will have bloomed by then). We use binary search to efficiently find the smallest day where check(day) returns true, which gives us our answer in O(n * log(max(bloomDay))) time instead of O(n * max(bloomDay)) if we checked every day.
Learn more about Binary Search patterns.
Solution Implementation
1class Solution:
2 def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
3 """
4 Find the minimum number of days to wait to make m bouquets from the garden.
5 Each bouquet requires k adjacent flowers to bloom.
6
7 Args:
8 bloomDay: List where bloomDay[i] is the day when the i-th flower blooms
9 m: Number of bouquets needed
10 k: Number of adjacent flowers needed for each bouquet
11
12 Returns:
13 Minimum number of days to wait, or -1 if impossible
14 """
15
16 # Early termination: impossible if we don't have enough flowers
17 if m * k > len(bloomDay):
18 return -1
19
20 def feasible(days: int) -> bool:
21 """
22 Check if we can make m bouquets after waiting 'days' days.
23 Returns True if we can make at least m bouquets.
24 """
25 bouquets_made = 0
26 consecutive_bloomed = 0
27
28 for bloom_day in bloomDay:
29 if bloom_day <= days:
30 consecutive_bloomed += 1
31 if consecutive_bloomed == k:
32 bouquets_made += 1
33 consecutive_bloomed = 0
34 else:
35 consecutive_bloomed = 0
36
37 return bouquets_made >= m
38
39 # Binary search using the template pattern
40 left, right = min(bloomDay), max(bloomDay)
41 first_true_index = -1
42
43 while left <= right:
44 mid = (left + right) // 2
45
46 if feasible(mid):
47 first_true_index = mid
48 right = mid - 1 # Search for earlier day
49 else:
50 left = mid + 1
51
52 return first_true_index
531class Solution {
2 private int[] bloomDay;
3 private int requiredBouquets;
4 private int flowersPerBouquet;
5
6 /**
7 * Finds the minimum number of days to wait for making m bouquets from the garden
8 * @param bloomDay Array where bloomDay[i] is the day when the i-th flower blooms
9 * @param m Number of bouquets needed
10 * @param k Number of adjacent flowers needed for one bouquet
11 * @return Minimum days to wait, or -1 if impossible
12 */
13 public int minDays(int[] bloomDay, int m, int k) {
14 this.bloomDay = bloomDay;
15 this.requiredBouquets = m;
16 this.flowersPerBouquet = k;
17
18 // Early termination: impossible if we don't have enough flowers
19 if ((long) m * k > bloomDay.length) {
20 return -1;
21 }
22
23 // Find min and max bloom days for search bounds
24 int minDay = Integer.MAX_VALUE;
25 int maxDay = Integer.MIN_VALUE;
26 for (int day : bloomDay) {
27 minDay = Math.min(minDay, day);
28 maxDay = Math.max(maxDay, day);
29 }
30
31 // Binary search using the template pattern
32 int left = minDay;
33 int right = maxDay;
34 int firstTrueIndex = -1;
35
36 while (left <= right) {
37 int mid = left + (right - left) / 2;
38
39 if (feasible(mid)) {
40 firstTrueIndex = mid;
41 right = mid - 1; // Search for earlier day
42 } else {
43 left = mid + 1;
44 }
45 }
46
47 return firstTrueIndex;
48 }
49
50 /**
51 * Checks if we can make the required number of bouquets within given days
52 * @param days Number of days to wait
53 * @return true if we can make at least m bouquets, false otherwise
54 */
55 private boolean feasible(int days) {
56 int bouquetCount = 0;
57 int consecutiveFlowers = 0;
58
59 for (int bloomTime : bloomDay) {
60 if (bloomTime <= days) {
61 consecutiveFlowers++;
62 if (consecutiveFlowers == flowersPerBouquet) {
63 bouquetCount++;
64 consecutiveFlowers = 0;
65 }
66 } else {
67 consecutiveFlowers = 0;
68 }
69 }
70
71 return bouquetCount >= requiredBouquets;
72 }
73}
741class Solution {
2public:
3 int minDays(vector<int>& bloomDay, int m, int k) {
4 // Early termination: impossible if we don't have enough flowers
5 if ((long long) m * k > bloomDay.size()) {
6 return -1;
7 }
8
9 // Find min and max bloom days for search bounds
10 int minDay = ranges::min(bloomDay);
11 int maxDay = ranges::max(bloomDay);
12
13 // Lambda function to check if we can make m bouquets by day 'days'
14 auto feasible = [&](int days) {
15 int bouquetCount = 0;
16 int consecutiveFlowers = 0;
17
18 for (int bloomDayOfFlower : bloomDay) {
19 if (bloomDayOfFlower <= days) {
20 consecutiveFlowers++;
21 if (consecutiveFlowers == k) {
22 bouquetCount++;
23 consecutiveFlowers = 0;
24 }
25 } else {
26 consecutiveFlowers = 0;
27 }
28 }
29
30 return bouquetCount >= m;
31 };
32
33 // Binary search using the template pattern
34 int left = minDay;
35 int right = maxDay;
36 int firstTrueIndex = -1;
37
38 while (left <= right) {
39 int mid = left + (right - left) / 2;
40
41 if (feasible(mid)) {
42 firstTrueIndex = mid;
43 right = mid - 1; // Search for earlier day
44 } else {
45 left = mid + 1;
46 }
47 }
48
49 return firstTrueIndex;
50 }
51};
521/**
2 * Finds the minimum number of days to wait for m bouquets with k adjacent flowers each
3 * @param bloomDay - Array where bloomDay[i] is the day the i-th flower blooms
4 * @param m - Number of bouquets needed
5 * @param k - Number of adjacent flowers needed per bouquet
6 * @returns Minimum days to wait, or -1 if impossible
7 */
8function minDays(bloomDay: number[], m: number, k: number): number {
9 // Early termination: impossible if we don't have enough flowers
10 if (m * k > bloomDay.length) {
11 return -1;
12 }
13
14 // Find min and max bloom days for search bounds
15 const minBloomDay: number = Math.min(...bloomDay);
16 const maxBloomDay: number = Math.max(...bloomDay);
17
18 /**
19 * Checks if we can make m bouquets within the given number of days
20 * @param days - Number of days to wait
21 * @returns True if m bouquets can be made, false otherwise
22 */
23 const feasible = (days: number): boolean => {
24 let bouquetCount: number = 0;
25 let consecutiveFlowers: number = 0;
26
27 for (const bloomTime of bloomDay) {
28 if (bloomTime <= days) {
29 consecutiveFlowers++;
30 if (consecutiveFlowers === k) {
31 bouquetCount++;
32 consecutiveFlowers = 0;
33 }
34 } else {
35 consecutiveFlowers = 0;
36 }
37 }
38
39 return bouquetCount >= m;
40 };
41
42 // Binary search using the template pattern
43 let left: number = minBloomDay;
44 let right: number = maxBloomDay;
45 let firstTrueIndex: number = -1;
46
47 while (left <= right) {
48 const mid: number = Math.floor((left + right) / 2);
49
50 if (feasible(mid)) {
51 firstTrueIndex = mid;
52 right = mid - 1; // Search for earlier day
53 } else {
54 left = mid + 1;
55 }
56 }
57
58 return firstTrueIndex;
59}
60Solution Approach
The solution implements binary search to find the minimum number of days needed to make m bouquets.
Early Termination:
Before starting the binary search, we check if it's even possible to make m bouquets. If m * k > len(bloomDay), there aren't enough flowers, so we return -1 immediately.
Feasible Function:
The feasible(days) function determines if we can make at least m bouquets by a given day:
- Initialize
bouquetCountandconsecutiveFlowersto 0 - Iterate through each flower in
bloomDay:- If
bloomDay[i] <= days, the flower has bloomed, so incrementconsecutiveFlowers - Otherwise, reset
consecutiveFlowersto 0 (break in consecutive sequence) - When
consecutiveFlowers == k, we've found a complete bouquet:- Increment
bouquetCountby 1 - Reset
consecutiveFlowersto 0 to start counting the next bouquet
- Increment
- If
- Return
TrueifbouquetCount >= m, otherwiseFalse
Binary Search Template:
We use the standard binary search template to find the first day where feasible(day) returns True:
left, right = min(bloomDay), max(bloomDay)
first_true_index = -1
while left <= right:
mid = (left + right) // 2
if feasible(mid):
first_true_index = mid
right = mid - 1 # Search for earlier day
else:
left = mid + 1
return first_true_index
The key insight is that the feasibility forms a monotonic pattern: [False, False, ..., False, True, True, ..., True]. Once we can make m bouquets on day d, we can always make them on any later day. We track first_true_index to remember the earliest valid day found, and use right = mid - 1 to continue searching for an even earlier day.
Time Complexity: O(n * log(max(bloomDay))) where n is the length of the array. We perform binary search over the range of days (log(max(bloomDay))), and for each mid-point, we check if it's valid in O(n) time.
Space Complexity: O(1) as we only use a constant amount of extra space.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Example: bloomDay = [7, 7, 7, 7, 12, 7, 7], m = 2, k = 3
We need to make 2 bouquets, each requiring 3 adjacent flowers.
Step 1: Initialize binary search
left = min(bloomDay) = 7right = max(bloomDay) = 12first_true_index = -1
Step 2: Binary search process (while left <= right)
Iteration 1: left = 7, right = 12, mid = 9
- Check
feasible(9): - Bloomed status:
[Yes, Yes, Yes, Yes, No, Yes, Yes](flower at index 4 blooms on day 12) - Traverse array:
- Indices 0-2: 3 consecutive flowers → bouquet #1, reset counter
- Index 3: 1 consecutive flower
- Index 4: Not bloomed, reset counter
- Indices 5-6: 2 consecutive flowers (not enough)
- Total bouquets: 1, need 2
- Result:
False, setleft = mid + 1 = 10
Iteration 2: left = 10, right = 12, mid = 11
- Check
feasible(11): - Same as day 9 (flower at index 4 still hasn't bloomed on day 11)
- Total bouquets: 1
- Result:
False, setleft = mid + 1 = 12
Iteration 3: left = 12, right = 12, mid = 12
- Check
feasible(12): - Bloomed status:
[Yes, Yes, Yes, Yes, Yes, Yes, Yes](all flowers have bloomed) - Traverse array:
- Indices 0-2: 3 consecutive flowers → bouquet #1, reset counter
- Indices 3-5: 3 consecutive flowers → bouquet #2, reset counter
- Index 6: 1 flower (leftover)
- Total bouquets: 2
- Result:
True, setfirst_true_index = 12,right = mid - 1 = 11
Iteration 4: left = 12, right = 11
left > right, exit loop
Step 3: Return result
Return first_true_index = 12. We need to wait 12 days to make 2 bouquets of 3 adjacent flowers each.
The binary search efficiently found that day 12 is the first day when we can make the required bouquets, avoiding the need to check every single day from 7 to 12.
Time and Space Complexity
The time complexity is O(n × log M), where n is the length of the bloomDay array (number of flowers) and M is the maximum value in bloomDay (maximum blooming day).
Breaking down the analysis:
- The
bisect_leftfunction performs binary search on the range[0, mx + 1], which takesO(log M)iterations - For each binary search iteration, the
checkfunction is called as the key function - The
checkfunction iterates through allnelements inbloomDay, takingO(n)time - Therefore, the total time complexity is
O(n × log M)
The space complexity is O(1) as the algorithm only uses a constant amount of extra space for variables like cnt, cur, l, and mx, regardless of the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Using Wrong Binary Search Template Variant
A common mistake is using the while left < right with right = mid variant instead of the standard template with first_true_index tracking.
Incorrect approach:
# WRONG: Different template variant while left < right: mid = (left + right) // 2 if feasible(mid): right = mid else: left = mid + 1 return left
Correct approach:
Use the standard template with first_true_index to track the answer:
first_true_index = -1 while left <= right: mid = (left + right) // 2 if feasible(mid): first_true_index = mid right = mid - 1 else: left = mid + 1 return first_true_index
2. Misunderstanding Adjacent Flower Requirement
A common mistake is thinking that any k flowers that have bloomed can form a bouquet, rather than requiring them to be consecutive/adjacent in the garden.
Incorrect approach:
def feasible_wrong(days: int) -> bool:
# WRONG: Just counting total bloomed flowers
bloomed_count = sum(1 for d in bloomDay if d <= days)
return bloomed_count >= m * k
Correct approach: Track consecutive bloomed flowers and reset the counter when encountering an unbloomed flower or after forming a bouquet.
3. Not Resetting Counter After Making a Bouquet
Forgetting to reset the consecutive flower counter after successfully forming a bouquet leads to overcounting.
Incorrect implementation:
def feasible_wrong(days: int) -> bool:
bouquets_made = 0
consecutive_bloomed = 0
for bloom_day in bloomDay:
if bloom_day <= days:
consecutive_bloomed += 1
if consecutive_bloomed == k:
bouquets_made += 1
# WRONG: Forgot to reset consecutive_bloomed!
else:
consecutive_bloomed = 0
return bouquets_made >= m
Solution:
Always reset consecutive_bloomed = 0 after incrementing bouquets_made.
4. Integer Overflow in Early Termination Check
In languages with fixed integer sizes, m * k might overflow for large values.
Prevention:
Cast to long before multiplication: if (long) m * k > bloomDay.length.
5. Not Handling Edge Cases
Forgetting to check if it's mathematically impossible to create the required bouquets.
Essential check:
if m * k > len(bloomDay):
return -1
This should be done before the binary search to avoid unnecessary computation.
A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".
What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?
Recommended Readings
https assets algo monster cover_photos Binary_Search svg Binary Search Intuition Binary search is an efficient array search algorithm It works by narrowing down the search range by half each time If you have looked up a word in a physical dictionary you've already used binary search in real life Let's
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion If you prefer videos here's a video that explains recursion in a fun and easy way Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask him
Want a Structured Path to Master System Design Too? Don’t Miss This!