-
Notifications
You must be signed in to change notification settings - Fork 2
feat(algorithms, intervals): count days without meetings #128
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
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
140449f
feat(algorithms, intervals): count days without meetings
BrianLusina 7f523ef
updating DIRECTORY.md
8829a96
refactor(algorithms, intervals, count days): add return type
BrianLusina 69e581c
refactor(algorithms, intervals, count days): add type hints
BrianLusina 911b34e
refactor(algorithms, intervals, count days): early return for empty list
BrianLusina 33819d4
refactor(algorithms, intervals, count days): update constraints in doc
BrianLusina 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # Count Days Without Meetings | ||
|
|
||
| You are given a positive integer, `days`, which represents the total number of days an employee is available for work, | ||
| starting from day 1. You are also given a 2D array, `meetings`, where each entry meetings[i] = [starti, endi] indicates | ||
| that a meeting is scheduled from day starti to day endi (both inclusive). | ||
|
|
||
| Your task is to count the days when the employee is available for work but has no scheduled meetings. | ||
|
|
||
| > Note: The meetings may overlap. | ||
|
|
||
| ## Constraints | ||
|
|
||
| - 1 <= days <= 10^5 | ||
| - 1 <= meetings.length <= 10^3 | ||
| - meetings[i].length == 2 | ||
| - 1 <= `meetings[i][0]` <= `meetings[i][1]` <= days | ||
|
|
||
| ## Examples | ||
|
|
||
|  | ||
|  | ||
|  | ||
|
|
||
| ## Solution | ||
|
|
||
| The core idea of this solution is to merge overlapping meetings into continuous intervals to efficiently track the | ||
| occupied days. We begin by sorting the meetings to process them sequentially. As we iterate, we merge overlapping | ||
| meetings while counting the occupied days whenever gaps appear. Finally, subtracting the total occupied days from the | ||
| available days gives the number of free days. | ||
|
|
||
| Using the intuition above, we implement the algorithm as follows: | ||
|
|
||
| 1. First, sort the meetings based on their start time to process them in order. | ||
| 2. Initialize a variable, occupied, with 0 to count the days when the employee has scheduled meetings. | ||
| 3. Initialize two variables, start and end, with the first meeting’s start and end times. These variables define the | ||
| beginning and end of the merged meeting interval to efficiently track continuously occupied periods. | ||
| 4. Iterate through the remaining meetings: | ||
| - If a meeting overlaps with the current merged meeting, extend the end time to merge it into the existing interval. | ||
| - Otherwise, add the days of the merged meeting to occupied as `occupied = occupied + (end - start + 1)`. Then, update | ||
| the start and end for the next interval. | ||
| 5. After the loop, add the days of the last merged interval to occupied. | ||
| 6. Return the difference between days and occupied (`days−occupied`), representing the number of days when the employee | ||
| is available for work but has no scheduled meetings. | ||
|
|
||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|  | ||
|
|
||
| ### Time Complexity | ||
|
|
||
| The algorithm’s time complexity is O(nlogn), where n is the size of the meetings array. This is due to the sorting step, | ||
| which dominates the overall complexity while merging the intervals runs in O(n). | ||
|
|
||
| ### Space Complexity | ||
|
|
||
| The algorithm’s space complexity is constant, O(1). |
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,110 @@ | ||
| from typing import List | ||
|
|
||
|
|
||
| def count_days(days: int, meetings: List[List[int]]) -> int: | ||
| """ | ||
| Counts the number of days the employee is available for work but has no scheduled meetings. | ||
|
|
||
| Complexity: | ||
|
|
||
| Standard time complexity for sorting is O(n log(n)). The loop is O(n). The part that dominates the overall time | ||
| complexity is the sorting and the loop. It amounts to O(n log(n)) as the overall. The overall space complexity for | ||
| this approach is O(1) without accounting for the in place sorting that is taking place which is O(n) using timsort | ||
| in Python. | ||
|
|
||
| Summary of Performance | ||
| --- | ||
| Metric Complexity Reason | ||
| --- | ||
| Time O(nlogn) Dominated by the initial sort of n meetings. | ||
| Space O(n) Required by Timsort for internal temporary storage. | ||
|
|
||
| Args: | ||
| days (int): The total number of days the employee is available for work | ||
| meetings (List[List[int]]): A list of meetings, where each meeting is represented as a list of two integers [start, end] | ||
| Returns: | ||
| int: The number of days the employee is available for work but has no scheduled meetings | ||
| """ | ||
| # sort meetings by start in place, incurs O(n log(n)) time complexity | ||
| meetings.sort(key=lambda x: x[0]) | ||
|
|
||
| # keep track of free days | ||
| free_days = 0 | ||
|
|
||
| # a pointer that keeps track of the current day | ||
| last_busy_day = 0 | ||
|
|
||
| # iterate through the meetings, for each meeting we might have a gap | ||
| for meeting in meetings: | ||
| # get the start and end of the meeting | ||
| start, end = meeting | ||
|
|
||
| # calculate gaps, if the meeting starts at start and our last_busy_day is less than start - 1, the days in | ||
| # between are free | ||
| if start > last_busy_day + 1: | ||
| free_days += (start - 1) - last_busy_day | ||
|
|
||
| # update the last busy day to the maximum of the last busy day and the end of the meeting | ||
|
|
||
| # This ensures that if a meeting is completely contained within a previous busy block, the boundary doesn't move | ||
| # backward, which handles overlaps perfectly. | ||
| last_busy_day = max(last_busy_day, end) | ||
|
|
||
| # add the remaining days to the free days | ||
| return free_days + (days - last_busy_day) | ||
|
|
||
|
|
||
| def count_days_2(days: int, meetings: List[List[int]]) -> int: | ||
| """ | ||
| Counts the number of days the employee is available for work but has no scheduled meetings. | ||
|
|
||
| This implementation merges overlapping meetings and counts total occupied days. | ||
|
|
||
| Time Complexity: O(n log n) due to sorting | ||
| Space Complexity: O(1) excluding sort overhead | ||
|
|
||
| Args: | ||
| days (int): The total number of days the employee is available for work | ||
| meetings (List[List[int]]): A list of meetings, where each meeting is represented as a list of two integers [start, end] | ||
| Note: This function modifies the input list by sorting it in place. | ||
| Returns: | ||
| int: The number of days the employee is available for work but has no scheduled meetings | ||
| """ | ||
| # Sort the meetings based on their start time to process them in order | ||
| meetings.sort() | ||
|
|
||
| # Initialize a variable with 0 to count the number of days when the employee has meetings scheduled | ||
| occupied = 0 | ||
|
|
||
| # Initialize two variables with the first meeting’s start and end times | ||
| # Sort the meetings based on their start time to process them in order | ||
| meetings.sort() | ||
|
|
||
| # Handle edge case of empty meetings | ||
| if not meetings: | ||
| return days | ||
|
|
||
| # Initialize a variable with 0 to count the number of days when the employee has meetings scheduled | ||
| occupied = 0 | ||
|
|
||
| # Initialize two variables with the first meeting's start and end times | ||
| start, end = meetings[0] | ||
BrianLusina marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # Iterate through the remaining meetings | ||
| for i in range(1, len(meetings)): | ||
| # If a meeting overlaps with the current merged meeting | ||
| if meetings[i][0] <= end: | ||
| # Extend the end time to merge it | ||
| end = max(end, meetings[i][1]) | ||
| else: | ||
| # Add the days of the merged meeting | ||
| occupied += end - start + 1 | ||
|
|
||
| # Update start and end for the next interval | ||
| start, end = meetings[i] | ||
|
|
||
| # Add the days of the last merged meeting | ||
| occupied += end - start + 1 | ||
|
|
||
| # Return the free days | ||
| return days - occupied | ||
Binary file added
BIN
+58.2 KB
.../intervals/count_days/images/examples/count_days_without_meetings_example_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+55.8 KB
.../intervals/count_days/images/examples/count_days_without_meetings_example_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+62 KB
.../intervals/count_days/images/examples/count_days_without_meetings_example_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+65.4 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+63.9 KB
...tervals/count_days/images/solutions/count_days_without_meetings_solution_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+83 KB
...tervals/count_days/images/solutions/count_days_without_meetings_solution_11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+75.9 KB
...tervals/count_days/images/solutions/count_days_without_meetings_solution_12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+53.3 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+62.8 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+78.9 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+76.4 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+103 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+61.4 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+80.2 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+101 KB
...ntervals/count_days/images/solutions/count_days_without_meetings_solution_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
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.