【一看就会一写就废 指间算法】重新安排会议得到最多空余时间 I—— 滑动窗口、贪心

46 阅读2分钟

指尖划过的轨迹,藏着最细腻的答案~

题目:

给你一个整数 eventTime 表示一个活动的总时长,这个活动开始于 t = 0 ,结束于 t = eventTime

同时给你两个长度为 n 的整数数组 startTimeendTime 。它们表示这次活动中 n 个时间 没有重叠 的会议,其中第 i 个会议的时间为 [startTime[i], endTime[i]]

你可以重新安排 至多 k 个会议,安排的规则是将会议时间平移,且保持原来的 会议时长 ,你的目的是移动会议后 最大化 相邻两个会议之间的 最长 连续空余时间。

移动前后所有会议之间的 相对 顺序需要保持不变,而且会议时间也需要保持互不重叠。

请你返回重新安排会议以后,可以得到的 最大 空余时间。

注意,会议 不能 安排到整个活动的时间以外。

示例 1:

输入:eventTime = 5, k = 1, startTime = [1,3], endTime = [2,5]
输出:2
解释:

[1, 2] 的会议安排到 [2, 3] ,得到空余时间 [0, 2]

示例 2:

输入:eventTime = 10, k = 1, startTime = [0,2,9], endTime = [1,4,10]
输出:6
解释:

[2, 4] 的会议安排到 [1, 3] ,得到空余时间 [3, 9]

示例 3:

输入:eventTime = 5, k = 2, startTime = [0,1,2,3,4], endTime = [1,2,3,4,5]
输出:0
解释:
活动中的所有时间都被会议安排满了。

提示:

1eventTime1091 \leq eventTime \leq 10^9
n==startTime.length==endTime.lengthn == startTime.length == endTime.length
2n1052 \leq n \leq 10^5
1kn1 \leq k \leq n
0startTime[i]<endTime[i]eventTime0 \leq startTime[i] < endTime[i] \leq eventTime
endTime[i]startTime[i+1]endTime[i] \leq startTime[i + 1] 其中 i 在范围 [0, n - 2] 之间。

分析:

题目要求每次只可以移动k个会议,为了寻找最大的空闲时间,我们肯定会贪心的将k个会议全部移动,毕竟移动的越多必会得到更大的空闲时间,那问题就转换为在k次移动中的最大空闲时间,k为定值,我们可以使用定长滑动窗口

那怎么呢?我们需要的是空闲时间,每个会议有左右两个空闲时间,k次移动就会有k+1个空闲时间。我们可以将所有空闲时间存入一个数组中,寻找数组中长度为k+1的窗口的最大值即是最终的答案。

AC代码:

class Solution {
public:
    int maxFreeTime(int eventTime, int k, vector<int>& startTime, vector<int>& endTime) {
        int ans = 0, sum = 0;
        int n = startTime.size();

        auto get = [&](int i) -> int {
            if (i == 0) {
                return startTime[0];
            } else if (i == n) {
                return eventTime - endTime[n - 1];
            }

            return startTime[i] - endTime[i - 1];
        };

        for (int i = 0; i <= n; i++) {
            sum += get(i);

            int left = i - k;
            if (left < 0) {
                continue;
            }

            ans = max(ans, sum);

            sum -= get(left);
        }

        return ans;
    }
};