You are given an integer eventTime
denoting the duration of an event. You are also given two integer arrays startTime
and endTime
, each of length n
. These represent the start and end times of n
non-overlapping meetings that occur during the event between time t = 0
and time t = eventTime
, where the i<sup>th</sup>
meeting occurs during the time [startTime[i], endTime[i]].
You can reschedule at most one meeting by moving its start time while maintaining the same duration, such that the meetings remain non-overlapping, to maximize the longest continuous period of free time during the event.
Return the maximum amount of free time possible after rearranging the meetings.
Note that the meetings can not be rescheduled to a time outside the event and they should remain non-overlapping.
Note: In this version, it is valid for the relative ordering of the meetings to change after rescheduling one meeting.
Example 1:
eventTime = 5, startTime = [1,3], endTime = [2,5]
Output: 2
Explanation: Reschedule the meeting at [1, 2]
to [2, 3]
, leaving no meetings during the time [0, 2]
.
Example 2:
eventTime = 10, startTime = [0,7,9], endTime = [1,8,10]
Output: 7
Explanation: Reschedule the meeting at [0, 1]
to [8, 9]
, leaving no meetings during the time [0, 7]
.
What is the most efficient way to implement this function?
## Naive Approach
The simplest approach is to iterate through all possible meetings, and for each meeting, try to reschedule it to every possible valid time slot. For each rescheduling, calculate the maximum free time and keep track of the maximum.
1. **Iterate through Meetings:** For each meeting, consider it for rescheduling.
2. **Iterate through Possible Time Slots:** For each meeting, iterate through all possible start times to which it can be moved.
3. **Check Validity:** Ensure the new time slot doesn't overlap with other meetings and stays within the event time.
4. **Calculate Free Time:** Calculate the longest continuous free time for each valid rescheduling.
5. **Update Maximum:** Keep track of the maximum free time found so far.
```python
def max_free_time_naive(eventTime, startTime, endTime):
n = len(startTime)
max_free = 0
for i in range(n):
original_start = startTime[i]
original_end = endTime[i]
duration = original_end - original_start
# Remove the current meeting from the schedule temporarily
temp_start_times = startTime[:i] + startTime[i+1:]
temp_end_times = endTime[:i] + endTime[i+1:]
for new_start in range(eventTime - duration + 1):
new_end = new_start + duration
# Check for overlaps with other meetings
overlap = False
for j in range(n - 1):
if not (new_end <= temp_start_times[j] or new_start >= temp_end_times[j]):
overlap = True
break
if not overlap:
# Calculate free time with the new schedule
combined_start_times = temp_start_times + [new_start]
combined_end_times = temp_end_times + [new_end]
# Sort by start time
meetings = sorted(zip(combined_start_times, combined_end_times))
max_current_free = 0
current_free = meetings[0][0]
max_current_free = max(max_current_free, current_free)
for k in range(n - 1):
current_free = meetings[k+1][0] - meetings[k][1]
max_current_free = max(max_current_free, current_free)
current_free = eventTime - meetings[-1][1]
max_current_free = max(max_current_free, current_free)
max_free = max(max_free, max_current_free)
# Also consider the case where no rescheduling happens
meetings = sorted(zip(startTime, endTime))
max_current_free = 0
current_free = meetings[0][0]
max_current_free = max(max_current_free, current_free)
for k in range(n - 1):
current_free = meetings[k+1][0] - meetings[k][1]
max_current_free = max(max_current_free, current_free)
current_free = eventTime - meetings[-1][1]
max_current_free = max(max_current_free, current_free)
max_free = max(max_free, max_current_free)
return max_free
The optimal approach involves sorting the meetings by their start times, identifying gaps, and then trying to maximize these gaps by rescheduling one meeting.
def max_free_time_optimal(eventTime, startTime, endTime):
meetings = sorted(zip(startTime, endTime))
n = len(meetings)
max_free = 0
# Calculate initial gaps
gaps = []
gaps.append(meetings[0][0]) # Gap at the beginning
for i in range(n - 1):
gaps.append(meetings[i+1][0] - meetings[i][1])
gaps.append(eventTime - meetings[-1][1]) # Gap at the end
# Calculate initial max free time
max_free = max(gaps)
# Try rescheduling each meeting
for i in range(n):
original_start = meetings[i][0]
original_end = meetings[i][1]
duration = original_end - original_start
# Try moving the meeting to fill each gap
for j in range(len(gaps)):
# Calculate potential new start time
if j == 0:
new_start = 0
elif j == len(gaps) - 1:
new_start = eventTime - duration
else:
new_start = meetings[j][0] # This is wrong, should be using the previous end time
new_start = meetings[j-1][1]
new_end = new_start + duration
if new_start < 0:
continue
if new_end > eventTime:
continue
# Check for overlap with other meetings
overlap = False
for k in range(n):
if i == k:
continue
if not (new_end <= meetings[k][0] or new_start >= meetings[k][1]):
overlap = True
break
if not overlap:
temp_meetings = []
for k in range(n):
if i != k:
temp_meetings.append(meetings[k])
temp_meetings.append((new_start, new_end))
temp_meetings = sorted(temp_meetings)
new_gaps = []
new_gaps.append(temp_meetings[0][0]) # Gap at the beginning
for k in range(len(temp_meetings) - 1):
new_gaps.append(temp_meetings[k+1][0] - temp_meetings[k][1])
new_gaps.append(eventTime - temp_meetings[-1][1]) # Gap at the end
max_free = max(max_free, max(new_gaps))
return max_free
Optimal Approach:
Sorting: O(n log n), where n is the number of meetings.
Initial Gaps Calculation: O(n)
Rescheduling Loop:
So, the rescheduling loop is O(n * n * n) = O(n^3)
Overall: O(n log n) + O(n) + O(n^3) which simplifies to O(n^3)
Optimal Approach:
So, the overall space complexity is O(n).