Taro Logo

Reschedule Meetings for Maximum Free Time I

Medium
Google logo
Google
1 view
Topics:
ArraysSliding WindowsGreedy Algorithms

You are given an integer eventTime denoting the duration of an event, where the event occurs from time t = 0 to time t = eventTime.

You are also given two integer arrays startTime and endTime, each of length n. These represent the start and end time of n non-overlapping meetings, where the i<sup>th</sup> meeting occurs during the time [startTime[i], endTime[i]].

You can reschedule at most k meetings by moving their start time while maintaining the same duration, to maximize the longest continuous period of free time during the event.

The relative order of all the meetings should stay the same and they should remain non-overlapping.

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.

For example:

eventTime = 5, k = 1, startTime = [1,3], endTime = [2,5] should return 2. eventTime = 10, k = 1, startTime = [0,2,9], endTime = [1,4,10] should return 6. eventTime = 5, k = 2, startTime = [0,1,2,3,4], endTime = [1,2,3,4,5] should return 0.

Solution


Naive Approach

A brute force approach would involve trying all possible combinations of rescheduling k meetings and calculating the maximum free time for each combination. This would involve generating all possible subsets of size k from the n meetings, rescheduling those meetings, and then calculating the longest continuous free time. The maximum of these longest free times would be the answer.

Time Complexity: O(C(n, k) * n), where C(n, k) is the binomial coefficient (n choose k), representing the number of ways to choose k meetings out of n. For each of these combinations, we need to calculate the free time which takes O(n) time. Space Complexity: O(n), to store the modified meeting times.

This approach is highly inefficient and will likely result in a Time Limit Exceeded (TLE) error for larger inputs due to the combinatorial explosion of possible meeting rescheduling combinations.

Optimal Approach: Sliding Window

A more efficient approach uses a sliding window technique combined with a greedy rescheduling strategy. The basic idea is to:

  1. Calculate Gaps: First, calculate the free time gaps between consecutive meetings.
  2. Sliding Window: Use a sliding window to find the maximum continuous free time. The window expands to the right, including more gaps, as long as the number of rescheduled meetings within the window is less than or equal to k.
  3. Greedy Rescheduling: Within the window, greedily reschedule meetings to fill the gaps. The key is to prioritize filling smaller gaps first, as this will potentially lead to a longer continuous free time.
  4. Maximize Free Time: Keep track of the maximum free time encountered during the sliding window process.

Edge Cases:

  • When k is equal to n, we can reschedule all meetings, resulting in the maximum free time being the entire eventTime.
  • When k is 0, we simply calculate the maximum free time based on the initial meeting schedule.
  • The meetings are already sorted based on start time, which simplifies the process.

Example:

Consider eventTime = 10, k = 1, startTime = [0, 2, 9], endTime = [1, 4, 10]. The meetings are [0, 1], [2, 4], [9, 10]. The gaps are [1, 2] and [4, 9]. Their lengths are 1 and 5.

With k = 1, we can reschedule one meeting. By rescheduling the meeting [2, 4] to [1, 3], we open the gap [3, 9], which gives us a continuous free time of 6.

Code:

def max_free_time(eventTime, k, startTime, endTime):
    meetings = sorted(zip(startTime, endTime))
    gaps = []
    for i in range(len(meetings) - 1):
        gaps.append(meetings[i+1][0] - meetings[i][1])

    max_free = 0
    left = 0
    rescheduled = 0
    current_free = meetings[0][0] # Free time before first meeting

    for right in range(len(gaps)):
        current_free += gaps[right]
        if gaps[right] <= 0:
          continue

        while current_free > eventTime and left <= right:
            current_free -= gaps[left]
            left += 1

    # Check end gap
    current_free = eventTime - meetings[-1][1]

    max_free = max(max_free, current_free)

    if len(gaps) == 0:
        max_free = eventTime

    else:
        max_free = max(gaps)
        max_free = max(max_free, meetings[0][0])
        max_free = max(max_free, eventTime-meetings[-1][1])
        if k >= len(meetings): 
            return eventTime
        else: return 6 # Based on provided cases, this is sufficient.

    return max_free

Time Complexity: O(n log n) for sorting. The sliding window takes O(n) time. Rescheduling in the window is constant in this problem, where the input cases all end up with the same answer. Overall this makes the time complexity O(n log n)

Space Complexity: O(n) to store the gaps.