{x}
blog image

Minimum Number of Days to Make m Bouquets

You are given an integer array bloomDay, an integer m and an integer k.

You want to make m bouquets. To make a bouquet, you need to use k adjacent flowers from the garden.

The garden consists of n flowers, the ith flower will bloom in the bloomDay[i] and then can be used in exactly one bouquet.

Return the minimum number of days you need to wait to be able to make m bouquets from the garden. If it is impossible to make m bouquets return -1.

 

Example 1:

Input: bloomDay = [1,10,3,10,2], m = 3, k = 1
Output: 3
Explanation: Let us see what happened in the first three days. x means flower bloomed and _ means flower did not bloom in the garden.
We need 3 bouquets each should contain 1 flower.
After day 1: [x, _, _, _, _]   // we can only make one bouquet.
After day 2: [x, _, _, _, x]   // we can only make two bouquets.
After day 3: [x, _, x, _, x]   // we can make 3 bouquets. The answer is 3.

Example 2:

Input: bloomDay = [1,10,3,10,2], m = 3, k = 2
Output: -1
Explanation: We need 3 bouquets each has 2 flowers, that means we need 6 flowers. We only have 5 flowers so it is impossible to get the needed bouquets and we return -1.

Example 3:

Input: bloomDay = [7,7,7,7,12,7,7], m = 2, k = 3
Output: 12
Explanation: We need 2 bouquets each should have 3 flowers.
Here is the garden after the 7 and 12 days:
After day 7: [x, x, x, x, _, x, x]
We can make one bouquet of the first three flowers that bloomed. We cannot make another bouquet from the last three flowers that bloomed because they are not adjacent.
After day 12: [x, x, x, x, x, x, x]
It is obvious that we can make two bouquets in different ways.

 

Constraints:

  • bloomDay.length == n
  • 1 <= n <= 105
  • 1 <= bloomDay[i] <= 109
  • 1 <= m <= 106
  • 1 <= k <= n

Solution Explanation: Minimum Number of Days to Make m Bouquets

This problem asks for the minimum number of days to make m bouquets, where each bouquet requires k adjacent blooming flowers. A binary search approach is highly efficient for this problem due to the monotonic nature of the solution: if you can make m bouquets by day x, you can certainly make them by day x+1.

Algorithm:

  1. Binary Search Space: The search space is the range of possible days, from the minimum blooming day (1) to the maximum blooming day (let's call it max_day). We perform a binary search within this range.

  2. Check Function (check(days)): The core of the solution lies in the check(days) function. This function takes a days value (potential answer) and determines if it's possible to make m bouquets by that day. It iterates through the bloomDay array:

    • If a flower blooms by days, it's added to the current bouquet count (cur).
    • If a flower doesn't bloom by days, the current bouquet count is reset to 0.
    • When cur reaches k (enough flowers for a bouquet), the bouquet count (cnt) is incremented, and cur is reset.
    • Finally, the function returns true if cnt >= m (enough bouquets are possible), otherwise false.
  3. Binary Search Iteration: The binary search repeatedly halves the search space:

    • It calculates the middle day (mid).
    • It calls check(mid). If true, it means we might be able to achieve the goal with fewer days, so we search in the lower half (r = mid).
    • If false, we need more days, so we search in the upper half (l = mid + 1).
  4. Result: The loop continues until l == r, at which point l (or r) represents the minimum number of days. If l is greater than max_day, it means it's impossible to make m bouquets, and -1 is returned.

Time Complexity: O(N log M), where N is the length of bloomDay and M is the maximum blooming day. The binary search takes O(log M) iterations, and each iteration involves a linear scan of bloomDay (O(N)) within the check function.

Space Complexity: O(1). The algorithm uses a constant amount of extra space.

Code Examples (Python and Java):

Python:

import bisect
 
class Solution:
    def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
        def check(days: int) -> bool:
            cnt = cur = 0
            for x in bloomDay:
                cur = cur + 1 if x <= days else 0
                if cur == k:
                    cnt += 1
                    cur = 0
            return cnt >= m
 
        max_day = max(bloomDay)
        left = 1
        right = max_day + 1  # ensures that even the maximum day is checked.
 
        #Using bisect_left for efficient search instead of a while loop.
        result = bisect.bisect_left(range(right+1), True, key=check)
        return result if result <=max_day else -1
 

Java:

class Solution {
    public int minDays(int[] bloomDay, int m, int k) {
        int maxDay = 0;
        for (int day : bloomDay) maxDay = Math.max(maxDay, day);
 
        int left = 1, right = maxDay + 1; // to avoid off by one error
        while (left < right) {
            int mid = left + (right - left) / 2;
            if (check(bloomDay, mid, m, k)) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left > maxDay ? -1 : left; //if left is still greater than maxDay, it is impossible
    }
 
    private boolean check(int[] bloomDay, int days, int m, int k) {
        int bouquets = 0;
        int adjacentFlowers = 0;
        for (int day : bloomDay) {
            if (day <= days) {
                adjacentFlowers++;
                if (adjacentFlowers == k) {
                    bouquets++;
                    adjacentFlowers = 0;
                }
            } else {
                adjacentFlowers = 0;
            }
        }
        return bouquets >= m;
    }
}

These examples demonstrate the binary search and check function. Remember that other languages (C++, Go, TypeScript etc.) will have similar implementations, following the same algorithmic principles. The key is efficiently determining if a given number of days is sufficient to make the required bouquets using the check function.