-
Notifications
You must be signed in to change notification settings - Fork 2
feat(algorithms, intervals, flowers bloom): full bloom flowers #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
BrianLusina
merged 3 commits into
main
from
feat/algorithms-intervals-full-bloom-flowers
Dec 26, 2025
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Number of Flowers in Full Bloom | ||
|
|
||
| You are given a 0-indexed 2D integer array, flowers, where each element flowers[i]=[starti ,endi] represents the time | ||
| interval during which the ith flower is in full bloom (inclusive). | ||
|
|
||
| You are also given a 0-indexed integer array, people, of size n, where people[i] denotes the time at which the ith person | ||
| arrives to view the flowers. For each person, determine how many flowers are in full bloom at their arrival time. | ||
| Return an integer array, ans, of length n, where ans[i] is the number of blooming flowers when the ith person arrives. | ||
|
|
||
| ## Constraints | ||
|
|
||
| - 1 <= flowers.length <= 10^3 | ||
| - `flowers[i].length` == 2 | ||
| - 1 <= starti <= endi <= 10^4 | ||
| - 1 <= people.length <= 10^3 | ||
| - 1 <= people[i] <= 10^4 | ||
|
|
||
| ### Solution | ||
|
|
||
| The core intuition behind this solution is to avoid directly simulating flower blooming across all possible time values, | ||
| which would be inefficient. Instead, we transform the problem into one of counting intervals using binary search. The | ||
| challenge is to determine a person’s arrival time. The difference between these two counts gives the number of flowers | ||
| in bloom at that moment. | ||
|
|
||
| To achieve this, the solution separates the flowers’ intervals into two lists: one for start times and one for end times. | ||
| The key trick is that the end times are stored as endi+1 instead of endi. This ensures that when a person arrives at | ||
| exactly endi, the flower is still counted as blooming. With both lists sorted, we can use binary search to quickly | ||
| determine counts for any arrival time. | ||
|
|
||
| Let’s break down the key steps of the solution: | ||
|
|
||
| 1. Initialize the starts and ends arrays for storing start and end times, respectively. | ||
| 2. Iterate over each flower interval [starti, endi]. | ||
| - Add starti to the starts list. | ||
| - Add endi+1 to the ends list. | ||
| 3. Sort both lists to ensure that binary search can efficiently count the number of flowers that started or ended before | ||
| a given arrival time. | ||
| 4. Create an ans list of size n to store the answer for each person. | ||
| 5. Iterate over people array and for each person’s arrival time, perform two binary searches: | ||
| - On starts, find how many flowers began blooming at or before the arrival time. | ||
| - On ends, find how many flowers had already finished blooming before the arrival time. | ||
| - Store the difference between the counts in the ans array. | ||
| 6. After completing the iteration, return the ans array as the output. | ||
|
|
||
| Binary Search implementation details: | ||
| - The binarySearch function is a modified version of the standard algorithm. | ||
| - It returns the index of the first element greater than the target (upper bound). | ||
| - This effectively gives the count of values ≤ target. | ||
|
|
||
| ### Time Complexity | ||
|
|
||
| - Creating the starts and ends arrays of length n takes O(n) time. | ||
| - Sorting both arrays costs O(nlogn). | ||
| - Next, for each of the m people, we perform two binary searches on these arrays, each taking O(logn) time. This | ||
| contributes O(mlogn) in total. | ||
|
|
||
| So, the overall time complexity is O(nlogn+mlogn), which simplifies to O((n+m)logn). | ||
|
|
||
| ### Space Complexity | ||
|
|
||
| The space complexity is O(n) because the solution stores all n flowers’ start and end times in separate lists (starts | ||
| and ends). So, the overall space complexity is O(n). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| from typing import List | ||
| from bisect import bisect_right, bisect_left | ||
|
|
||
|
|
||
| def full_bloom_flowers(flowers: List[List[int]], people: List[int]) -> List[int]: | ||
| # if there are no flowers, then we can return an empty list | ||
| if not flowers: | ||
| return [] | ||
|
|
||
| # sorted list of start and end times for the periods of blooming flowers | ||
| start_times = sorted([start for start, _ in flowers]) | ||
| end_times = sorted([end for _, end in flowers]) | ||
|
|
||
| # This keeps track of the number of flowers that are in full bloom at each person's arrival time | ||
| result = [] | ||
|
|
||
| for persons_arrival_time in people: | ||
| # Counts every flower that started at or before the arrival | ||
| flowers_in_bloom_before_arrival = bisect_right( | ||
| start_times, persons_arrival_time | ||
| ) | ||
| # Counts only flowers that ended strictly before the arrival, leaving the ones ending at that time in the "blooming" tally. | ||
| flowers_not_in_bloom_before_arrival = bisect_left( | ||
| end_times, persons_arrival_time | ||
| ) | ||
| count = flowers_in_bloom_before_arrival - flowers_not_in_bloom_before_arrival | ||
| result.append(count) | ||
|
|
||
| return result | ||
|
|
||
|
|
||
| def full_bloom_flowers_2(flowers: List[List[int]], people: List[int]) -> List[int]: | ||
| starts = [] | ||
| ends = [] | ||
|
|
||
| for start, end in flowers: | ||
| starts.append(start) | ||
| ends.append(end + 1) | ||
|
|
||
| starts.sort() | ||
| ends.sort() | ||
| ans = [] | ||
|
|
||
| for person in people: | ||
| i = bisect_right(starts, person) | ||
| j = bisect_right(ends, person) | ||
| ans.append(i - j) | ||
|
|
||
| return ans |
35 changes: 35 additions & 0 deletions
35
algorithms/intervals/full_bloom_flowers/test_full_bloom_flowers.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import unittest | ||
| from typing import List | ||
| from parameterized import parameterized | ||
| from algorithms.intervals.full_bloom_flowers import ( | ||
| full_bloom_flowers, | ||
| full_bloom_flowers_2, | ||
| ) | ||
|
|
||
| TEST_CASES = [ | ||
| ([[5, 5]], [5], [1]), | ||
| ([[3, 3], [3, 3], [3, 3]], [2, 3, 4], [0, 3, 0]), | ||
| ([[2, 4], [6, 8]], [1, 5, 9], [0, 0, 0]), | ||
| ([[1, 4], [2, 5], [3, 6]], [1, 2, 3, 4, 5, 6], [1, 2, 3, 3, 2, 1]), | ||
| ([[1, 2], [100, 200], [300, 400]], [1, 150, 250, 350, 500], [1, 1, 0, 1, 0]), | ||
| ] | ||
|
|
||
|
|
||
| class FullBloomFlowersTestCase(unittest.TestCase): | ||
| @parameterized.expand(TEST_CASES) | ||
| def test_full_bloom_flowers( | ||
| self, flowers: List[List[int]], people: List[int], expected: List[int] | ||
| ): | ||
| actual = full_bloom_flowers(flowers, people) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
| @parameterized.expand(TEST_CASES) | ||
| def test_full_bloom_flowers( | ||
| self, flowers: List[List[int]], people: List[int], expected: List[int] | ||
| ): | ||
| actual = full_bloom_flowers_2(flowers, people) | ||
| self.assertEqual(expected, actual) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.