目标
给你一个整数 eventTime 表示一个活动的总时长,这个活动开始于 t = 0 ,结束于 t = eventTime 。
同时给你两个长度为 n 的整数数组 startTime 和 endTime 。它们表示这次活动中 n 个时间 没有重叠 的会议,其中第 i 个会议的时间为 [startTime[i], endTime[i]] 。
你可以重新安排 至多 一个会议,安排的规则是将会议时间平移,且保持原来的 会议时长 ,你的目的是移动会议后 最大化 相邻两个会议之间的 最长 连续空余时间。
请你返回重新安排会议以后,可以得到的 最大 空余时间。
注意,会议 不能 安排到整个活动的时间以外,且会议之间需要保持互不重叠。
注意:重新安排会议以后,会议之间的顺序可以发生改变。
示例 1:
输入:eventTime = 5, startTime = [1,3], endTime = [2,5]
输出:2
解释:
将 [1, 2] 的会议安排到 [2, 3] ,得到空余时间 [0, 2] 。
示例 2:
输入:eventTime = 10, startTime = [0,7,9], endTime = [1,8,10]
输出:7
解释:
将 [0, 1] 的会议安排到 [8, 9] ,得到空余时间 [0, 7] 。
示例 3:
输入:eventTime = 10, startTime = [0,3,7,9], endTime = [1,4,8,10]
输出:6
解释:
将 [3, 4] 的会议安排到 [8, 9] ,得到空余时间 [1, 7] 。
示例 4:
输入:eventTime = 5, startTime = [0,1,2,3,4], endTime = [1,2,3,4,5]
输出:0
解释:
活动中的所有时间都被会议安排满了。
说明:
- 1 <= eventTime <= 10^9
- n == startTime.length == endTime.length
- 2 <= n <= 10^5
- 0 <= startTime[i] < endTime[i] <= eventTime
- endTime[i] <= startTime[i + 1] 其中 i 在范围 [0, n - 2] 之间。
思路
有一个活动有 n 个时间不重叠的会议,重新安排 1
个会议议程,使得空余时间最大。
与 3439.重新安排会议得到最多空余时间I 相比,本题只能重新安排一个会议,但是允许打乱原有的会议顺序。
对于当前会议,如果除了其左右两侧的空余位置之外存在空余位置大于会议时间,那么空余时间是其左右两侧的空余时间加上会议时间。否则,可以将会议左移或者右移到边界,空余时间为左右空余时间之和。
因此可以求出前三大的空余时间,如果会议时间小于等于第三大的空余时间,说明总是可以移到左右空余之外。否则就需要判断当前空余时间是否大于第二、第一大的空余时间,以及是否恰好是其左右空余。
代码
/**
* @date 2025-07-10 22:15
*/
public class MaxFreeTime3440 {
public int maxFreeTime(int eventTime, int[] startTime, int[] endTime) {
int n = startTime.length;
int[] gap = new int[n + 1];
int[] intervals = new int[n];
Arrays.setAll(intervals, i -> endTime[i] - startTime[i]);
int[] a = new int[]{0, 0};
int[] b = new int[]{0, 0};
int[] c = new int[]{0, 0};
for (int i = 0; i <= n; i++) {
if (i == 0) {
gap[i] = startTime[i];
} else if (i == n) {
gap[i] = eventTime - endTime[i - 1];
} else {
gap[i] = startTime[i] - endTime[i - 1];
}
if (gap[i] >= a[0]) {
c = b;
b = a;
a = new int[]{gap[i], i};
} else if (gap[i] >= b[0]) {
c = b;
b = new int[]{gap[i], i};
} else if (gap[i] >= c[0]) {
c = new int[]{gap[i], i};
}
}
int res = a[0];
for (int i = 0; i < n; i++) {
int g = gap[i] + gap[i + 1];
if (intervals[i] > a[0]) {
res = Math.max(res, g);
} else if (intervals[i] <= c[0]) {
res = Math.max(res, g + intervals[i]);
} else if (intervals[i] <= b[0] && (b[1] != i && b[1] != i + 1)) {
res = Math.max(res, g + intervals[i]);
} else if (a[1] != i && a[1] != i + 1) {
res = Math.max(res, g + intervals[i]);
} else {
res = Math.max(res, g);
}
}
return res;
}
}