LeetCode #1482 Medium

Minimum Number of Days to Make m Bouquets

Minimum Number of Days to Make m Bouquets: bloomDay[i] is the day flower i blooms. A bouquet needs k adjacent bloomed flowers. Return the minimum number of days to wait to make m bouquets, or -1 if it is impossible.

Constraints
  • bloomDay.length == n
  • 1 <= n <= 10⁵
  • 1 <= bloomDay[i] <= 10⁹
  • 1 <= m <= 10⁶
  • 1 <= k <= n
binary-searcharraybinary-search-on-answer
Open on LeetCode ↗
02

Intuition

Minimum number of days to make m bouquets finds the earliest day when m bouquets can be made, each needing k adjacent flowers that have already bloomed. The answer is a day number, and days have a natural order — which is the opening for binary search: - Waiting longer never makes fewer bouquets possible, so feasibility is monotonic in the day, and binary search applies to the day itself. That is binary search on the answer, not on the array, so the input order must be preserved. For a candidate day, the check is a single linear scan. Walk the flowers counting consecutive blooms — those whose bloom day is at most the candidate. Each time the run reaches k, count a bouquet and reset the run to zero. Any flower not yet bloomed also resets it. Resetting to zero after forming a bouquet is essential. Leaving the counter running lets the same flowers be reused across overlapping bouquets, which the adjacency requirement forbids, and the check then reports feasible far too early. The search range runs from the minimum bloom day to the maximum. Below the minimum nothing has bloomed; above the maximum nothing more will change. One check comes before the search: if m × k exceeds the flower count, there are not enough flowers to ever succeed, so return −1. The multiplication can overflow on large inputs, so compare as m > n / k or use a wider type. Each feasibility check is O(n) and the range halves each step, giving O(n log(maxDay − minDay)).

How to spot this pattern

Binary search the answer over days, with a linear feasibility check that counts completed runs of k adjacent bloomed flowers. Monotonicity holds because flowers never un-bloom: if day d works, every later day works too. The search range is min(bloomDay) to max(bloomDay) — only actual bloom days can be answers.

03

Approach

Try it first

Before reading on: price up what the direct approach costs here, then ask what property lets you throw away half the range after one comparison. Aim for O(n log max(bloomDay)) time and O(1) space.

1

Spot the monotonic predicate

Waiting longer never reduces the bouquets available, so feasibility flips from false to true exactly once — the condition binary search needs.

2

Rule out impossible inputs first

If m bouquets of k flowers exceed the total, return -1. Compare as m > n / k — the multiplication overflows on large inputs.

3

Set the search range

Search days from the minimum bloom day to the maximum. Below the first nothing has bloomed; above the last nothing further changes.

4

Count consecutive blooms

For a candidate day, scan once counting runs of flowers bloomed by then. A flower not yet bloomed breaks the run and resets the counter.

5

Reset after each bouquet

Set the run back to zero once k flowers are gathered. Letting it continue reuses the same flowers across bouquets and reports success far too early.

6

Narrow toward the earliest day

When a day is feasible, record it and search earlier; otherwise search later. The loop converges on the minimum workable day.

7

Cost of the search

Each check is O(n) and the range halves each step, giving O(n log(maxDay − minDay)) time and O(1) space.

04

Solution & live demo

▶1class Solution:
▶2 def minDays(self, bloomDay, m, k):
▶3 if m * k > len(bloomDay):
▶4 return -1
▶5 lo, hi, best = min(bloomDay), max(bloomDay), -1
▶6 while lo <= hi:
▶7 day = (lo + hi) // 2
▶8 made, run = 0, 0
▶9 for b in bloomDay:
▶10 if b <= day:
▶11 run += 1
▶12 if run == k:
▶13 made += 1
▶14 run = 0
▶15 else:
▶16 run = 0
▶17 if made >= m:
▶18 best = day
▶19 hi = day - 1
▶20 else:
▶21 lo = day + 1
▶22 return best
05

Common pitfalls

Skipping the impossibility check

✗ Wrong
lo, hi = min(bloomDay), max(bloomDay)
✓ Right
if m * k > len(bloomDay):
    return -1

If the garden has fewer than m * k flowers total, no day ever suffices and the search returns the initial -1 only by accident of initialisation. Testing up front makes the impossible case explicit and correct.

Not resetting the run counter after completing a bouquet

✗ Wrong
if run == k:
    made += 1
✓ Right
if run == k:
    made += 1
    run = 0

Bouquets consume their flowers. Leaving run at k means every subsequent bloomed flower completes another bouquet from the same stems, wildly overcounting and accepting far too early a day.

Leaving the run intact across an unbloomed flower

✗ Wrong
if b <= day:
    run += 1
✓ Right
if b <= day:
    run += 1
    ...
else:
    run = 0

The k flowers must be adjacent. An unbloomed flower breaks the chain, so the counter has to restart — otherwise runs are stitched together across gaps that don't exist.

06

Edge cases

m * k > number of flowers

Impossible regardless of waiting; return -1 before starting the search.

k == 1

Adjacency stops mattering — any m bloomed flowers suffice. The counting pass handles this without a special branch since every run of length 1 immediately banks a bouquet.

Runs longer than k

A run of 2k yields two bouquets. Resetting the run counter to 0 after each bouquet (rather than decrementing by k) gives the same result and is simpler.

All flowers bloom on the same day

The answer is that day, provided enough flowers exist. The search collapses to a single value.

07

Complexity

Time
O(n log max(bloomDay))
Space
O(1)
One linear counting pass per probe. Trying every day from 1 to max would be O(n x max) and far too slow.