2025-08-08:重新安排会议得到最多空余时间Ⅰ。用go语言,你有一个整数 eventTime,表示整个活动从时间 0 开始,到时间 eventTime 结束的总时长。
同时,你有两个等长数组 startTime 和 endTime,表示这期间有 n 个不重叠的会议,每个会议 i 的时间区间是 [startTime[i], endTime[i]]。
你可以对最多 k 个会议进行时间上的调整。调整的方法是整体平移会议时间段,但不改变会议长度。你的目标是通过合理移动这几个会议,最大化任意两个相邻会议之间的最长连续空闲时间。
调整时需要满足:
1.会议的新顺序和原有顺序一致;
2.会议时间段依然互不重叠;
3.会议时间不能超出整个活动时间区间 [0, eventTime]。
请你计算并返回,在重新安排后,能够达到的最大连续空闲时间。
1 <= eventTime <= 1000000000。
n == startTime.length == endTime.length。
2 <= n <= 100000。
1 <= k <= n。
0 <= startTime[i] < endTime[i] <= eventTime。
endTime[i] <= startTime[i + 1] 其中 i 在范围 [0, n - 2] 之间。
输入:eventTime = 10, k = 1, startTime = [0,2,9], endTime = [1,4,10]。
输出:6。
解释:
在这里插入图片描述
将 [2, 4] 的会议安排到 [1, 3] ,得到空余时间 [3, 9] 。
题目来自力扣3439。
给定的示例是:
eventTime = 10
k = 1
startTime = [0, 2, 9]
endTime = [1, 4, 10]
初始的会议时间区间是:
初始的空闲时间是:
最大空闲时间是 5。
现在可以调整最多 k = 1
个会议。调整会议 1 [2, 4] 到 [1, 3]:
新的空闲时间是:
最大空闲时间是 6,因此输出 6。
我们需要找到一种方法,通过调整最多 k
个会议的位置,使得相邻会议之间的空闲时间最大化。关键在于如何高效地计算调整后的空闲时间。
startTime[i+1] - endTime[i]
。我们需要最大化这些值中的最小值(或者直接找到最大的空闲时间)。i
向左移动(即提前),那么 startTime[i]
会减小,endTime[i]
也会减小相同的量(因为会议长度不变)。这会:startTime[i] - endTime[i-1]
(与前一个会议的空闲时间)startTime[i+1] - endTime[i]
(与后一个会议的空闲时间)k
个会议),计算调整这些会议后能够获得的最大空闲时间。[0, eventTime]
。k
个会议),尝试将这些会议向左或向右移动,以增加某个空闲时间。以示例为例: 初始会议:
空闲时间:
调整 k=1
个会议:
endTime
是 1,不能重叠)。因此,最佳调整是移动会议 1 到 [1, 3],得到最大空闲时间 6。
O(n)
,因为需要遍历所有会议。O(n)
个窗口),计算调整后的空闲时间是 O(1)
(因为只需要计算窗口前后的空闲时间)。O(n)
。O(n)
。O(n)
。O(1)
。O(n)
(如果存储所有空闲时间)或 O(1)
(如果即时计算)。在给定的代码中,没有显式存储所有空闲时间,而是即时计算和比较,因此额外空间复杂度是 O(1)
。
res
为 0,t
为 0(t
表示当前窗口内会议的总长度)。i
从 0 到 n-1
):t
。left
:i <= k-1
,left
是 0(窗口从最左边开始)。left
是 endTime[i-k]
(窗口的左边是第 i-k
个会议的结束时间)。right
:i == n-1
,right
是 eventTime
(窗口到最右边)。right
是 startTime[i+1]
(窗口的右边是第 i+1
个会议的开始时间)。right - left - t
,并更新 res
。i >= k-1
,从 t
中减去最早加入的会议的长度(滑动窗口的左移)。res
。以示例为例:
eventTime = 10
, k = 1
, startTime = [0, 2, 9]
, endTime = [1, 4, 10]
。n = 3
。res = 0
, t = 0
。遍历:
i = 0
:t += 1 - 0 = 1
。left = 0
(因为 i <= 0
)。right = startTime[1] = 2
。right - left - t = 2 - 0 - 1 = 1
。res = max(0, 1) = 1
。i >= 0
,t -= endTime[0] - startTime[0] = 1
,t = 0
。i = 1
:t += 4 - 2 = 2
。left = endTime[0] = 1
(因为 i > 0
)。right = startTime[2] = 9
。right - left - t = 9 - 1 - 2 = 6
。res = max(1, 6) = 6
。i >= 0
,t -= endTime[1] - startTime[1] = 2
,t = 0
。i = 2
:t += 10 - 9 = 1
。left = endTime[1] = 4
。right = eventTime = 10
。right - left - t = 10 - 4 - 1 = 5
。res = max(6, 5) = 6
。i >= 0
,t -= endTime[2] - startTime[2] = 1
,t = 0
。res = 6
。k
个会议后能够获得的最大空闲时间。每次调整时,窗口的左右边界由未调整的会议决定,窗口内的会议可以自由移动(不改变顺序、不重叠、不超出边界)。O(n)
,因为每个会议只被处理常数次。O(1)
,因为只使用了常数个额外变量。.
package main
import (
"fmt"
)
func maxFreeTime(eventTime int, k int, startTime []int, endTime []int)int {
n := len(startTime)
res := 0
t := 0
for i := 0; i < n; i++ {
t += endTime[i] - startTime[i]
var left int
if i <= k-1 {
left = 0
} else {
left = endTime[i-k]
}
var right int
if i == n-1 {
right = eventTime
} else {
right = startTime[i+1]
}
if right-left-t > res {
res = right - left - t
}
if i >= k-1 {
t -= endTime[i-k+1] - startTime[i-k+1]
}
}
return res
}
func main() {
eventTime := 10
k := 1
startTime := []int{0, 2, 9}
endTime := []int{1, 4, 10}
result := maxFreeTime(eventTime, k, startTime, endTime)
fmt.Println(result)
}
.
# -*-coding:utf-8-*-
def max_free_time(event_time, k, start_time, end_time):
n = len(start_time)
res = 0
t = 0
for i in range(n):
t += end_time[i] - start_time[i]
left = 0if i <= k - 1else end_time[i - k]
right = event_time if i == n - 1else start_time[i + 1]
if right - left - t > res:
res = right - left - t
if i >= k - 1:
t -= end_time[i - k + 1] - start_time[i - k + 1]
return res
if __name__ == "__main__":
event_time = 10
k = 1
start_time = [0, 2, 9]
end_time = [1, 4, 10]
result = max_free_time(event_time, k, start_time, end_time)
print(result)