2251. Number of Flowers in Full Bloom
Problem Description
You have information about when flowers bloom and when people arrive to see them.
Given:
- A 2D array
flowerswhere eachflowers[i] = [start_i, end_i]represents that the i-th flower blooms from daystart_ito dayend_i(both days inclusive) - An array
peoplewherepeople[i]represents the day when the i-th person arrives
You need to find out how many flowers are in full bloom when each person arrives.
For example, if a flower blooms from day 3 to day 7, and a person arrives on day 5, that flower would be counted as blooming for that person. If another flower blooms from day 1 to day 4, it would not be counted for this person since it has already wilted by day 5.
The solution uses a clever approach:
- Create two sorted lists: one with all bloom start times and one with all bloom end times
- For each person arriving at time
p:- Count how many flowers have started blooming by time
pusingbisect_right(start, p) - Count how many flowers have already finished blooming before time
pusingbisect_left(end, p) - The difference gives the number of flowers currently in bloom
- Count how many flowers have started blooming by time
The key insight is that bisect_right(start, p) counts all flowers that started at or before time p, while bisect_left(end, p) counts all flowers that ended strictly before time p. The difference between these two values gives the exact count of flowers blooming at time p.
Intuition
Think about what it means for a flower to be blooming at a specific time. A flower is blooming at time t if:
- It has already started blooming (its start time ≤
t) - It hasn't finished blooming yet (its end time ≥
t)
This naturally leads us to think about counting flowers in two groups:
- Flowers that have started by time
t - Flowers that have ended before time
t
The number of flowers blooming at time t = (flowers that have started) - (flowers that have already ended)
Instead of checking each flower individually for each person (which would be inefficient), we can preprocess the data. By separating all start times and end times into two sorted arrays, we can quickly answer "how many flowers have started/ended by time t" using binary search.
The trick with using bisect_right for starts and bisect_left for ends handles the boundary cases correctly:
bisect_right(start, p)counts all flowers wherestart_time <= pbisect_left(end, p)counts all flowers whereend_time < p
This is important because a flower that ends on day p should still be counted as blooming on day p (since the end time is inclusive). By using bisect_left for end times, we only exclude flowers that ended strictly before day p.
This transforms a potentially complex interval overlap problem into a simple counting problem using sorted arrays and binary search, achieving an efficient solution.
Learn more about Binary Search, Prefix Sum and Sorting patterns.
Solution Implementation
1from typing import List
2from bisect import bisect_right, bisect_left
3
4class Solution:
5 def fullBloomFlowers(
6 self, flowers: List[List[int]], people: List[int]
7 ) -> List[int]:
8 """
9 Calculate the number of flowers in bloom for each person's arrival time.
10
11 Args:
12 flowers: List of [start_time, end_time] representing bloom periods
13 people: List of arrival times for each person
14
15 Returns:
16 List of flower counts for each person
17 """
18 # Extract and sort all bloom start times
19 bloom_starts = sorted(start_time for start_time, _ in flowers)
20
21 # Extract and sort all bloom end times
22 bloom_ends = sorted(end_time for _, end_time in flowers)
23
24 # For each person, calculate flowers in bloom at their arrival time
25 result = []
26 for arrival_time in people:
27 # Count flowers that have started blooming by this time
28 flowers_started = bisect_right(bloom_starts, arrival_time)
29
30 # Count flowers that have already finished blooming before this time
31 flowers_ended = bisect_left(bloom_ends, arrival_time)
32
33 # The difference gives us flowers currently in bloom
34 flowers_in_bloom = flowers_started - flowers_ended
35 result.append(flowers_in_bloom)
36
37 return result
381class Solution {
2 public int[] fullBloomFlowers(int[][] flowers, int[] people) {
3 int flowerCount = flowers.length;
4
5 int[] startTimes = new int[flowerCount];
6 int[] endTimes = new int[flowerCount];
7
8 for (int i = 0; i < flowerCount; i++) {
9 startTimes[i] = flowers[i][0];
10 endTimes[i] = flowers[i][1];
11 }
12
13 Arrays.sort(startTimes);
14 Arrays.sort(endTimes);
15
16 int peopleCount = people.length;
17 int[] result = new int[peopleCount];
18
19 for (int i = 0; i < peopleCount; i++) {
20 // Count flowers with start <= arrivalTime (using target = arrivalTime + 1)
21 int flowersStarted = bisectLeft(startTimes, people[i] + 1);
22 // Count flowers with end < arrivalTime
23 int flowersEnded = bisectLeft(endTimes, people[i]);
24 result[i] = flowersStarted - flowersEnded;
25 }
26
27 return result;
28 }
29
30 // Binary search using first_true_index template
31 // Returns first index where nums[idx] >= target (count of elements < target)
32 private int bisectLeft(int[] nums, int target) {
33 int left = 0;
34 int right = nums.length - 1;
35 int firstTrueIndex = nums.length; // Default: no element >= target
36
37 while (left <= right) {
38 int mid = left + (right - left) / 2;
39 if (nums[mid] >= target) {
40 firstTrueIndex = mid;
41 right = mid - 1;
42 } else {
43 left = mid + 1;
44 }
45 }
46
47 return firstTrueIndex;
48 }
49}
501class Solution {
2public:
3 vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& people) {
4 vector<int> startTimes, endTimes;
5
6 for (const auto& flower : flowers) {
7 startTimes.push_back(flower[0]);
8 endTimes.push_back(flower[1]);
9 }
10
11 sort(startTimes.begin(), startTimes.end());
12 sort(endTimes.begin(), endTimes.end());
13
14 // Binary search using first_true_index template
15 auto bisectLeft = [](const vector<int>& nums, int target) -> int {
16 int left = 0;
17 int right = nums.size() - 1;
18 int firstTrueIndex = nums.size();
19
20 while (left <= right) {
21 int mid = left + (right - left) / 2;
22 if (nums[mid] >= target) {
23 firstTrueIndex = mid;
24 right = mid - 1;
25 } else {
26 left = mid + 1;
27 }
28 }
29 return firstTrueIndex;
30 };
31
32 vector<int> result;
33
34 for (const auto& personTime : people) {
35 // Count flowers with start <= personTime
36 int flowersStarted = bisectLeft(startTimes, personTime + 1);
37 // Count flowers with end < personTime
38 int flowersEnded = bisectLeft(endTimes, personTime);
39 result.push_back(flowersStarted - flowersEnded);
40 }
41
42 return result;
43 }
44};
451function fullBloomFlowers(flowers: number[][], people: number[]): number[] {
2 const flowerCount = flowers.length;
3
4 const startTimes = new Array(flowerCount).fill(0);
5 const endTimes = new Array(flowerCount).fill(0);
6
7 for (let i = 0; i < flowerCount; ++i) {
8 startTimes[i] = flowers[i][0];
9 endTimes[i] = flowers[i][1];
10 }
11
12 startTimes.sort((a, b) => a - b);
13 endTimes.sort((a, b) => a - b);
14
15 // Binary search using first_true_index template
16 // Returns first index where nums[idx] >= target
17 const bisectLeft = (nums: number[], target: number): number => {
18 let left = 0;
19 let right = nums.length - 1;
20 let firstTrueIndex = nums.length; // Default: no element >= target
21
22 while (left <= right) {
23 const mid = Math.floor((left + right) / 2);
24 if (nums[mid] >= target) {
25 firstTrueIndex = mid;
26 right = mid - 1;
27 } else {
28 left = mid + 1;
29 }
30 }
31 return firstTrueIndex;
32 };
33
34 const result: number[] = [];
35
36 for (const arrivalTime of people) {
37 // Count flowers with start <= arrivalTime
38 const flowersStarted = bisectLeft(startTimes, arrivalTime + 1);
39 // Count flowers with end < arrivalTime
40 const flowersEnded = bisectLeft(endTimes, arrivalTime);
41 result.push(flowersStarted - flowersEnded);
42 }
43
44 return result;
45}
46Solution Approach
The solution uses sorting and binary search to count blooming flowers.
Step 1: Extract and Sort Start/End Times
bloom_starts = sorted(start for start, _ in flowers)
bloom_ends = sorted(end for _, end in flowers)
Step 2: Binary Search Using first_true_index Template
For each person arriving at time p, we count:
- Flowers started: count of flowers with
start <= p - Flowers ended: count of flowers with
end < p
Using the first_true_index template to implement bisect_left:
def bisect_left(nums, target):
# Find first index where nums[idx] >= target
left, right = 0, len(nums) - 1
first_true_index = len(nums) # Default: no element >= target
while left <= right:
mid = (left + right) // 2
if nums[mid] >= target:
first_true_index = mid
right = mid - 1
else:
left = mid + 1
return first_true_index
Counting Logic:
flowers_started = bisect_left(starts, p + 1)counts flowers withstart <= pflowers_ended = bisect_left(ends, p)counts flowers withend < pblooming = flowers_started - flowers_ended
Why p + 1 for starts?
bisect_left(starts, p + 1) finds the first index where start >= p + 1, which equals the count of starts where start <= p.
Time Complexity: O((m + n) log m) where m = flowers, n = people.
Space Complexity: O(m) for sorted arrays.
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 understand how the solution works.
Given:
flowers = [[1,6], [3,7], [9,12], [4,13]]people = [2, 3, 7, 11]
Step 1: Extract and sort start/end times
From the flowers array, we extract:
- Start times:
[1, 3, 9, 4]→ Sorted:[1, 3, 4, 9] - End times:
[6, 7, 12, 13]→ Sorted:[6, 7, 12, 13]
Step 2: Process each person
For person at day 2:
bisect_right(start=[1,3,4,9], p=2)= 1- Only flower starting at day 1 has begun (1 ≤ 2)
bisect_left(end=[6,7,12,13], p=2)= 0- No flowers have ended yet (no end times < 2)
- Blooming flowers: 1 - 0 = 1
For person at day 3:
bisect_right(start=[1,3,4,9], p=3)= 2- Flowers starting at days 1 and 3 have begun (both ≤ 3)
bisect_left(end=[6,7,12,13], p=3)= 0- No flowers have ended yet (no end times < 3)
- Blooming flowers: 2 - 0 = 2
For person at day 7:
bisect_right(start=[1,3,4,9], p=7)= 3- Flowers starting at days 1, 3, and 4 have begun (all ≤ 7)
bisect_left(end=[6,7,12,13], p=7)= 1- Only the flower ending at day 6 has finished (6 < 7)
- Note: The flower ending at day 7 is still blooming!
- Blooming flowers: 3 - 1 = 2
For person at day 11:
bisect_right(start=[1,3,4,9], p=11)= 4- All flowers have started (all start times ≤ 11)
bisect_left(end=[6,7,12,13], p=11)= 2- Flowers ending at days 6 and 7 have finished (both < 11)
- Blooming flowers: 4 - 2 = 2
Result: [1, 2, 2, 2]
The key insight is how bisect_left for end times ensures flowers ending on the same day as a person's arrival are still counted as blooming, while bisect_right for start times includes flowers that start on the arrival day.
Time and Space Complexity
Time Complexity: O((m + n) × log n)
The time complexity breaks down as follows:
- Sorting the start times:
O(n log n)wherenis the number of flowers - Sorting the end times:
O(n log n)wherenis the number of flowers - For each person in
people, we perform:bisect_right(start, p):O(log n)binary searchbisect_left(end, p):O(log n)binary search- Since there are
mpeople, this step takesO(m × log n)
- Total:
O(n log n + n log n + m × log n)=O((m + n) × log n)
Space Complexity: O(n)
The space complexity consists of:
startarray:O(n)space to store all flower start timesendarray:O(n)space to store all flower end times- The result list uses
O(m)space but is not counted as auxiliary space since it's the output - Total auxiliary space:
O(n)
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Using Wrong Binary Search Template
The problem uses bisect_left which finds the first index where element >= target.
Wrong approach:
while left < right: mid = (left + right) >> 1 if nums[mid] >= target: right = mid else: left = mid + 1 return left # Returns left directly
Correct approach (first_true_index template):
first_true_index = len(nums) # Default
while left <= right:
mid = (left + right) // 2
if nums[mid] >= target:
first_true_index = mid
right = mid - 1
else:
left = mid + 1
return first_true_index
2. Confusing bisect_left vs bisect_right Logic
To count flowers with start <= p, use bisect_left(starts, p + 1) (not bisect_right).
To count flowers with end < p, use bisect_left(ends, p).
The key insight:
bisect_left(arr, x)returns count of elements < xbisect_left(arr, x + 1)returns count of elements <= x
3. Not Handling Inclusive Bloom Periods
Bloom periods are inclusive: a flower blooming [3, 5] is still blooming on day 5.
The formula bisect_left(ends, p) correctly counts only flowers with end < p, so flowers ending exactly on arrival day are still counted as blooming.
4. Incorrect Default for first_true_index
When no element >= target exists, first_true_index should default to len(nums) to correctly return "all elements are less than target".
Wrong: first_true_index = -1
Correct: first_true_index = len(nums)
What's the output of running the following function using the following tree as input?

1def serialize(root):
2 res = []
3 def dfs(root):
4 if not root:
5 res.append('x')
6 return
7 res.append(root.val)
8 dfs(root.left)
9 dfs(root.right)
10 dfs(root)
11 return ' '.join(res)
121import java.util.StringJoiner;
2
3public static String serialize(Node root) {
4 StringJoiner res = new StringJoiner(" ");
5 serializeDFS(root, res);
6 return res.toString();
7}
8
9private static void serializeDFS(Node root, StringJoiner result) {
10 if (root == null) {
11 result.add("x");
12 return;
13 }
14 result.add(Integer.toString(root.val));
15 serializeDFS(root.left, result);
16 serializeDFS(root.right, result);
17}
181function serialize(root) {
2 let res = [];
3 serialize_dfs(root, res);
4 return res.join(" ");
5}
6
7function serialize_dfs(root, res) {
8 if (!root) {
9 res.push("x");
10 return;
11 }
12 res.push(root.val);
13 serialize_dfs(root.left, res);
14 serialize_dfs(root.right, res);
15}
16Recommended 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
Prefix Sum Given an array of integers arr and a target value find a subarray that sums to the target Return the start and end indices of the subarray Input arr 1 20 3 30 5 4 target 7 Output 1 4 Explanation The subarray 20 3 30 from index 1 inclusive
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Want a Structured Path to Master System Design Too? Don’t Miss This!