757. 设置交集大小至少为2
题目描述
给你一个二维整数数组 intervals ,其中 intervals[i] = [starti, endi] 表示从 starti 到 endi 的所有整数,包括 starti 和 endi 。
包含集合 是一个名为 nums 的数组,并满足 intervals 中的每个区间都 至少 有 两个 整数在 nums 中。
- 例如,如果
intervals = [[1,3], [3,7], [8,9]],那么[1,2,4,7,8,9]和[2,3,4,8,9]都符合 包含集合 的定义。
返回包含集合可能的最小大小。
示例 1:
输入:intervals = [[1,3],[3,7],[8,9]] 输出:5 解释:nums = [2, 3, 4, 8, 9]. 可以证明不存在元素数量为 4 的包含集合。
示例 2:
输入:intervals = [[1,3],[1,4],[2,5],[3,5]] 输出:3 解释:nums = [2, 3, 4]. 可以证明不存在元素数量为 2 的包含集合。
示例 3:
输入:intervals = [[1,2],[2,3],[2,4],[4,5]] 输出:5 解释:nums = [1, 2, 3, 4, 5]. 可以证明不存在元素数量为 4 的包含集合。
提示:
1 <= intervals.length <= 3000intervals[i].length == 20 <= starti < endi <= 108
解法
方法一:排序 + 贪心
我们希望在数轴上选出尽可能少的整数点,使得每个区间都至少包含两个点。一个经典而有效的策略是按照区间的右端点进行排序,并尽量让已选取的点位于区间的右侧,以便这些点能覆盖更多后续区间。
首先将所有区间按照如下规则排序:
- 按右端点从小到大;
- 若右端点相同,按左端点从大到小。
这样排序的原因是:右端点越小的区间“可操作空间”越少,应优先满足;当右端点相同时,左端点更大的区间更窄,更应优先被处理。
随后,我们使用两个变量 \(s\) 和 \(e\) 分别记录当前所有已处理区间所共同拥有的 倒数第二个点 和 最后一个点。初始时 \(s = e = -1\),表示还没有放置任何点。
接下来依次处理排序后的区间 \([a, b]\),根据它与 \(\{s, e\}\) 的关系分三种情况讨论:
-
若 \(a \leq s\): 当前区间已包含 \(s\) 和 \(e\) 两个点,无需额外放点。
-
若 \(s < a \leq e\): 当前区间只包含一个点(即 \(e\)),还需要补一个点。为了让新点对后续区间最有帮助,我们选择在区间最右侧的点 \(b\)。此时更新 \(\textit{ans} = \textit{ans} + 1\),并将新的两点设为 \(\{e, b\}\)。
-
若 \(a > e\): 当前区间完全不包含已有的两个点,需要补两个点。最优选择是在区间最右侧放置 \(\{b - 1, b\}\)。此时更新 \(\textit{ans} = \textit{ans} + 2\),并将新的两点设为 \(\{b - 1, b\}\)。
最终返回总共放置的点数 \(\textit{ans}\)。
时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(\log n)\)。其中 \(n\) 为区间的数量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |