Facebook Pixel

3440. Reschedule Meetings for Maximum Free Time II

MediumGreedyArrayEnumeration
Leetcode Link

Problem Description

You are given an integer eventTime denoting the duration of an event. Additionally, you have two integer arrays startTime and endTime, each of length n. These arrays represent the start and end times of n non-overlapping meetings that occur during this event, ranging from time t = 0 to t = eventTime. The i-th meeting occurs during the time interval [startTime[i], endTime[i]].

Your task is to reschedule at most one meeting by changing its start time while keeping the duration the same, ensuring that the meetings remain non-overlapping. The goal is to maximize the longest continuous period of free time during the event.

Return the maximum amount of free time possible after rearranging the meetings. Meetings cannot be moved outside the event's timeframe, and they must remain non-overlapping. It's allowable for the order of the meetings to change after rescheduling one.

Intuition

To solve the problem, we need to focus on ensuring that meetings are rescheduled optimally for maximizing the free time periods, called gaps, between the meetings. Here's a structured approach to the problem:

  1. Compute Left Gaps: Calculate the free time between each meeting and the previous one when considering the event as starting. Maintain a running maximum of this gap through a left-to-right traversal.

  2. Compute Right Gaps: Calculate the free time between each meeting and the next one up until the event ends. This needs a right-to-left traversal to store the maximum gaps on the right.

  3. Evaluate Maximum Free Time:

    • For each meeting, using the stored left and right gaps, compute the potential maximum free time considering the possibility of rescheduling the meeting.
    • Consider the free time available if the current meeting were rescheduled, utilizing the left and right gaps to determine the best possible slot.
  4. Selection of Rescheduling:

    • For each meeting, evaluate if shifting would allow a greater continuous free time while keeping all the meetings non-overlapping.
    • The objective is to maximize the sum of left gap, right gap, and the meeting's interval if rescheduling is feasible.

This method effectively allows us to evaluate and maximize free time by efficiently using the precomputed gaps and making a single strategic reschedule decision.

Learn more about Greedy patterns.

Solution Approach

The solution leverages a dynamic approach by calculating gaps and efficiently determining where a meeting can be rescheduled to maximize free time. Here's a breakdown of the implemented algorithm and strategy:

  1. Initialization:

    • Determine the number of meetings n.
    • Use an array left_gaps to store the maximum gap between the start of the event and the current meeting if measured from the left. Initialize the first gap with startTime[0].
    • Use a second array right_gaps to store the maximum gap between the end of the current meeting and the end of the event if measured from the right. Initialize this with eventTime - endTime[-1].
  2. Calculate Left Gaps:

    • Iterate over meetings from the start to end.
    • For each meeting i, compute and store the maximum gap found from the left side up to meeting i, using left_gaps[i] = max(left_gaps[i - 1], startTime[i] - endTime[i - 1]).
  3. Calculate Right Gaps:

    • Iterate over meetings from end to start.
    • For each meeting i, compute and store the maximum gap found from the right side for meetings after i, using right_gaps[i] = max(right_gaps[i + 1], startTime[i + 1] - endTime[i]).
  4. Determine Possible Rescheduling:

    • Iterate through each meeting to calculate the potential maximum free time:
      • Calculate the left_gap directly from left_gaps.
      • Calculate the right_gap directly from right_gaps.
      • If rescheduling a meeting can overcome a gap on either side without conflict, consider the interval of the meeting for inclusion in the potential free time calculation.
      • Compute the potential free time as the sum of left_gap, right_gap, and interval (if applicable).
  5. Compute Result:

    • Throughout this process, maintain a variable res to store the maximum free time computed.
    • The final result is the maximum value of free time possible after evaluating all potential single-meeting rescheduling options.

This approach efficiently preprocesses gaps using dynamic programming techniques, enabling quick evaluation of rescheduling impacts to achieve maximal free time.

Ready to land your dream job?

Unlock your dream job with a 2-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's illustrate the solution approach using a small example:

Consider the following:

  • eventTime = 20
  • startTime = [2, 6, 10]
  • endTime = [4, 8, 12]

Step 1: Initialization

  • Number of meetings n = 3.
  • Initialize left_gaps to store maximum gaps from the start of the event:
    • left_gaps[0] = startTime[0] = 2
  • Initialize right_gaps to store maximum gaps to the end of the event:
    • right_gaps[2] = eventTime - endTime[2] = 20 - 12 = 8

Step 2: Calculate Left Gaps

  • For i = 1:

    • Calculate the gap before meeting 1: startTime[1] - endTime[0] = 6 - 4 = 2
    • Update: left_gaps[1] = max(left_gaps[0], 2) = 2
  • For i = 2:

    • Calculate the gap before meeting 2: startTime[2] - endTime[1] = 10 - 8 = 2
    • Update: left_gaps[2] = max(left_gaps[1], 2) = 2

Step 3: Calculate Right Gaps

  • For i = 1:

    • Calculate the gap after meeting 1: startTime[2] - endTime[1] = 10 - 8 = 2
    • Update: right_gaps[1] = max(right_gaps[2], 2) = 8
  • For i = 0:

    • Calculate the gap after meeting 0: startTime[1] - endTime[0] = 6 - 4 = 2
    • Update: right_gaps[0] = max(right_gaps[1], 2) = 8

Step 4: Determine Possible Rescheduling

Evaluate each meeting to see potential free time:

  • Rescheduling Meeting 0:

    • Available gaps: left_gap = 0, right_gap = right_gaps[0] = 8
    • Potential free time: 8 (considering moving the meeting around other gaps doesn't extend free time)
  • Rescheduling Meeting 1:

    • Available gaps: left_gap = left_gaps[1] = 2, right_gap = right_gaps[1] = 8
    • Potential free time: 2 + 8 = 10 (consider the full gap before or after)
  • Rescheduling Meeting 2:

    • Available gaps: left_gap = left_gaps[2] = 2, right_gap = 0
    • Potential free time: 2 (limited options)

Step 5: Compute Result

The maximum free time possible after evaluating rescheduling each meeting is 10. Thus, by rescheduling meeting 1 optimally, we can maximize the free time available during the event.

Solution Implementation

1from typing import List
2
3class Solution:
4    def maxFreeTime(
5        self, eventTime: int, startTime: List[int], endTime: List[int]
6    ) -> int:
7        n = len(startTime)  # Total number of meetings
8        max_free_time = 0  # Variable to hold the maximum free time found
9      
10        # Calculate the maximum gaps from the left side
11        left_gaps = [0] * n
12        left_gaps[0] = startTime[0]  # Free time before the first meeting starts
13        for i in range(1, n):
14            left_gaps[i] = max(left_gaps[i - 1], startTime[i] - endTime[i - 1])
15      
16        # Calculate the maximum gaps from the right side
17        right_gaps = [0] * n
18        right_gaps[n - 1] = eventTime - endTime[-1]  # Free time after the last meeting ends
19        for i in range(n - 2, -1, -1):
20            right_gaps[i] = max(right_gaps[i + 1], startTime[i + 1] - endTime[i])
21      
22        # Compute the maximum free time by evaluating each meeting
23        for i in range(n):
24            # Calculate the gap before the current meeting
25            left_gap = left_gaps[i] if i == 0 else startTime[i] - endTime[i - 1]
26            # Calculate the gap after the current meeting
27            right_gap = right_gaps[i] if i == n - 1 else startTime[i + 1] - endTime[i]
28          
29            # Calculate the total interval of free time
30            interval = 0
31            if (
32                i != 0
33                and left_gaps[i - 1] >= (endTime[i] - startTime[i])
34                or i != n - 1
35                and right_gaps[i + 1] >= (endTime[i] - startTime[i])
36            ):
37                interval = endTime[i] - startTime[i]
38          
39            # Update the maximum free time found
40            max_free_time = max(max_free_time, left_gap + interval + right_gap)
41      
42        return max_free_time
43
1import java.util.List;
2
3class Solution {
4    public int maxFreeTime(int eventTime, List<Integer> startTime, List<Integer> endTime) {
5        int n = startTime.size(); // Total number of meetings
6        int maxFreeTime = 0; // Variable to store maximum free time
7
8        // Calculate maximum gaps from the left side
9        int[] leftGaps = new int[n];
10        leftGaps[0] = startTime.get(0); // Free time before the first meeting starts
11        for (int i = 1; i < n; i++) {
12            leftGaps[i] = Math.max(leftGaps[i - 1], startTime.get(i) - endTime.get(i - 1));
13        }
14
15        // Calculate maximum gaps from the right side
16        int[] rightGaps = new int[n];
17        rightGaps[n - 1] = eventTime - endTime.get(n - 1); // Free time after the last meeting ends
18        for (int i = n - 2; i >= 0; i--) {
19            rightGaps[i] = Math.max(rightGaps[i + 1], startTime.get(i + 1) - endTime.get(i));
20        }
21
22        // Compute maximum free time by evaluating each meeting
23        for (int i = 0; i < n; i++) {
24            // Calculate the gap before the current meeting
25            int leftGap = (i == 0) ? leftGaps[i] : startTime.get(i) - endTime.get(i - 1);
26            // Calculate the gap after the current meeting
27            int rightGap = (i == n - 1) ? rightGaps[i] : startTime.get(i + 1) - endTime.get(i);
28
29            // Calculate the total interval of free time
30            int interval = 0;
31            if ((i != 0 && leftGaps[i - 1] >= (endTime.get(i) - startTime.get(i))) 
32                || (i != n - 1 && rightGaps[i + 1] >= (endTime.get(i) - startTime.get(i)))) {
33                // Interval only relevant if the gap exists
34                interval = endTime.get(i) - startTime.get(i);
35            }
36
37            // Update the maximum free time found
38            maxFreeTime = Math.max(maxFreeTime, leftGap + interval + rightGap);
39        }
40
41        return maxFreeTime;
42    }
43}
44
1#include <vector>
2#include <algorithm>
3using namespace std;
4
5class Solution {
6public:
7    int maxFreeTime(int eventTime, vector<int>& startTime, vector<int>& endTime) {
8        int n = startTime.size();  // Total number of meetings
9        int maxFreeTime = 0;  // Variable to hold the maximum free time found
10
11        // Calculate the maximum gaps from the left side
12        vector<int> leftGaps(n, 0);
13        leftGaps[0] = startTime[0];  // Free time before the first meeting starts
14        for (int i = 1; i < n; ++i) {
15            leftGaps[i] = max(leftGaps[i - 1], startTime[i] - endTime[i - 1]);
16        }
17
18        // Calculate the maximum gaps from the right side
19        vector<int> rightGaps(n, 0);
20        rightGaps[n - 1] = eventTime - endTime[n - 1];  // Free time after the last meeting ends
21        for (int i = n - 2; i >= 0; --i) {
22            rightGaps[i] = max(rightGaps[i + 1], startTime[i + 1] - endTime[i]);
23        }
24
25        // Compute the maximum free time by evaluating each meeting
26        for (int i = 0; i < n; ++i) {
27            // Calculate the gap before the current meeting
28            int leftGap = (i == 0) ? leftGaps[i] : startTime[i] - endTime[i - 1];
29            // Calculate the gap after the current meeting
30            int rightGap = (i == n - 1) ? rightGaps[i] : startTime[i + 1] - endTime[i];
31
32            // Calculate the total interval of free time
33            int interval = 0;
34            if ((i != 0 && leftGaps[i - 1] >= (endTime[i] - startTime[i]))
35                || (i != n - 1 && rightGaps[i + 1] >= (endTime[i] - startTime[i]))) {
36                interval = endTime[i] - startTime[i];
37            }
38
39            // Update the maximum free time found
40            maxFreeTime = max(maxFreeTime, leftGap + interval + rightGap);
41        }
42
43        return maxFreeTime;
44    }
45};
46
1// Importing List type from standard library for type safety
2type List = number[];
3
4// Function to calculate the maximum free time between meetings
5function maxFreeTime(eventTime: number, startTime: List, endTime: List): number {
6    const n = startTime.length;  // Total number of meetings
7    let maxFreeTime = 0;  // Variable to hold the maximum free time found
8
9    // Calculate the maximum gaps from the left side
10    const leftGaps: List = Array(n).fill(0);
11    leftGaps[0] = startTime[0];  // Free time before the first meeting starts
12    for (let i = 1; i < n; i++) {
13        leftGaps[i] = Math.max(leftGaps[i - 1], startTime[i] - endTime[i - 1]);
14    }
15
16    // Calculate the maximum gaps from the right side
17    const rightGaps: List = Array(n).fill(0);
18    rightGaps[n - 1] = eventTime - endTime[n - 1];  // Free time after the last meeting ends
19    for (let i = n - 2; i >= 0; i--) {
20        rightGaps[i] = Math.max(rightGaps[i + 1], startTime[i + 1] - endTime[i]);
21    }
22
23    // Compute the maximum free time by evaluating each meeting
24    for (let i = 0; i < n; i++) {
25        // Calculate the gap before the current meeting
26        const leftGap = i === 0 ? startTime[i] : startTime[i] - endTime[i - 1];
27        // Calculate the gap after the current meeting
28        const rightGap = i === n - 1 ? eventTime - endTime[i] : startTime[i + 1] - endTime[i];
29
30        // Calculate the total interval of free time
31        let interval = 0;
32        if (
33            (i !== 0 && leftGaps[i - 1] >= (endTime[i] - startTime[i])) ||
34            (i !== n - 1 && rightGaps[i + 1] >= (endTime[i] - startTime[i]))
35        ) {
36            interval = endTime[i] - startTime[i];
37        }
38
39        // Update the maximum free time found
40        maxFreeTime = Math.max(maxFreeTime, leftGap + interval + rightGap);
41    }
42
43    return maxFreeTime;
44}
45

Time and Space Complexity

The time complexity of the code is O(n), where n is the number of meetings (startTime and endTime lists' length). This is because the algorithm processes each meeting in several linear scans (left_gaps, right_gaps, and the final for loop), making it a linear time complexity operation.

The space complexity is O(n) as well, due to the use of two additional arrays, left_gaps and right_gaps, each of which holds n elements.

Learn more about how to find time and space complexity quickly.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:
Question 1 out of 10

How would you design a stack which has a function min that returns the minimum element in the stack, in addition to push and pop? All push, pop, min should have running time O(1).


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!


Load More