Skip to content

Commit 8a19ffb

Browse files
committed
refactor(algorithms, intervals): employee free time solution 2
1 parent 0353c09 commit 8a19ffb

20 files changed

+118
-1
lines changed

algorithms/intervals/employee_free_time/README.md

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ across all employees.
1818
![Example 2](./images/examples/employee_free_time_example_2.png)
1919
![Example 3](./images/examples/employee_free_time_example_3.png)
2020

21-
## Solution
21+
## Solution 1
2222

2323
The solution’s core revolves around merging overlapping intervals of employees and identifying the free time gaps
2424
between these merged intervals. Using a min-heap, we arrange the intervals based on when they start, sorting them
@@ -66,3 +66,64 @@ complexity of processing the heap is O(mlog(n)).
6666

6767
We use a heap in the solution, which can have a maximum of n elements. Hence, the space complexity of this solution is
6868
O(n), where n is the number of employees.
69+
70+
---
71+
72+
## Solution 2
73+
74+
This problems builds upon the concept of merging intervals. We can solve this problem by first merging all the employee
75+
meeting intervals into a single list. The free times are then the gaps between those merged intervals.
76+
77+
> Important Note on Boundaries: In this problem, we only consider the gaps between busy intervals as free time. We do not consider:
78+
> 1. Time before the earliest busy interval (e.g., if the first meeting starts at 9:00 AM, we don't count 8:00-9:00 AM as "free time")
79+
> 2. Time after the latest busy interval (e.g., if the last meeting ends at 5:00 PM, we don't count 5:00-6:00 PM as "free time")
80+
81+
This is because the problem asks for common free time when all employees are available, and we're only given their
82+
scheduled busy intervals within a certain working timeframe.
83+
84+
### Phase 1
85+
86+
We first want to flatten the list of intervals into a single list, and then sorting them by their start time to make the
87+
merge process easier.
88+
89+
![Solution 2.1](./images/solutions/employee_free_time_2_solution_1.png)
90+
![Solution 2.2](./images/solutions/employee_free_time_2_solution_2.png)
91+
92+
### Phase 2
93+
94+
Next, we want to merge all the intervals into a single list. We can do this by iterating through the list of intervals
95+
and comparing the end time of the current interval with the start time of the next interval. If the end time of the
96+
current interval is greater than or equal to the start time of the next interval, we merge the two intervals. Otherwise,
97+
we add the current interval to the merged list.
98+
99+
![Solution 2.3](./images/solutions/employee_free_time_2_solution_3.png)
100+
![Solution 2.4](./images/solutions/employee_free_time_2_solution_4.png)
101+
![Solution 2.5](./images/solutions/employee_free_time_2_solution_5.png)
102+
![Solution 2.6](./images/solutions/employee_free_time_2_solution_6.png)
103+
![Solution 2.7](./images/solutions/employee_free_time_2_solution_7.png)
104+
![Solution 2.8](./images/solutions/employee_free_time_2_solution_8.png)
105+
![Solution 2.9](./images/solutions/employee_free_time_2_solution_9.png)
106+
![Solution 2.10](./images/solutions/employee_free_time_2_solution_10.png)
107+
![Solution 2.11](./images/solutions/employee_free_time_2_solution_11.png)
108+
109+
### Phase 3
110+
111+
In this phase, we return the employee free times by finding the gaps between the merged intervals. We can do this by
112+
iterating through the merged intervals, and creating a new interval from the end time of the current interval and the
113+
start time of the next interval.
114+
115+
![Solution 2.12](./images/solutions/employee_free_time_2_solution_12.png)
116+
![Solution 2.13](./images/solutions/employee_free_time_2_solution_13.png)
117+
![Solution 2.14](./images/solutions/employee_free_time_2_solution_14.png)
118+
![Solution 2.15](./images/solutions/employee_free_time_2_solution_15.png)
119+
![Solution 2.16](images/solutions/employee_free_time_2_solution_15.png)
120+
121+
### Complexity Analysis
122+
123+
#### Time Complexity
124+
125+
O(n * logn) where n is the number of intervals. The time complexity is dominated by the sorting step.
126+
127+
#### Space Complexity
128+
129+
O(n) where n is the number of intervals. We need space for the free_times output array.

algorithms/intervals/employee_free_time/__init__.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,40 @@ def employee_free_time_heap(schedules: List[List[Interval]]) -> List[Interval]:
120120

121121
# When the heap is empty, return result.
122122
return free_time_slots
123+
124+
125+
def employee_free_time_2(schedules: List[List[Interval]]) -> List[Interval]:
126+
"""
127+
Finds intervals where employees have free time
128+
129+
Args:
130+
schedules(list): a list of lists, where each inner list contains `Interval` objects representing an employee's schedule.
131+
Returns:
132+
list: Intervals of employee free time
133+
"""
134+
# Flatten the list into a single list to make the merging process easier
135+
flattened_schedules: List[Interval] = [
136+
i for schedule in schedules for i in schedule
137+
]
138+
# sort the flattened list
139+
intervals = sorted(flattened_schedules, key=lambda i: i.start)
140+
141+
# This will contain the merged overlapping intervals
142+
merged: List[Interval] = []
143+
for current_interval in intervals:
144+
if not merged or merged[-1].end < current_interval.start:
145+
merged.append(current_interval)
146+
else:
147+
merged[-1].end = max(merged[-1].end, current_interval.end)
148+
149+
free_time_slots: List[Interval] = []
150+
# We iterate through the merged intervals finding the gaps between the intervals. A free slot is created by making
151+
# the end of the current merged interval the start and the start of the next interval the end.
152+
# So, if we have this [[1,2][3,4][5,6]], the free time slots are [[2,3],[4,5]]
153+
for idx in range(1, len(merged)):
154+
start = merged[idx - 1].end
155+
end = merged[idx].start
156+
free_interval = Interval(start=start, end=end)
157+
free_time_slots.append(free_interval)
158+
159+
return free_time_slots
35.3 KB
Loading
38.3 KB
Loading
37.6 KB
Loading
37 KB
Loading
39.3 KB
Loading
37.2 KB
Loading
41.9 KB
Loading
28.5 KB
Loading

0 commit comments

Comments
 (0)