中等
相关标签
相关企业
给定一个区间的集合 intervals
,其中 intervals[i] = [starti, endi]
。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
示例 1:
输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:
输入: intervals = [ [1,2], [1,2], [1,2] ] 输出: 2 解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:
输入: intervals = [ [1,2], [2,3] ] 输出: 0 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
提示:
1 <= intervals.length <= 105
intervals[i].length == 2
-5 * 104 <= starti < endi <= 5 * 104
class Solution {
/**
* 这个方法用于计算最少需要删除多少个区间,才能使剩余区间之间没有重叠。
* @param intervals 输入的区间数组
* @return 最少删除的区间数
*/
public int eraseOverlapIntervals(int[][] intervals) {
// 如果区间数组为空,则不需要删除任何区间
if (intervals.length == 0) {
return 0;
}
// 按照每个区间的起始时间对区间数组进行排序
Arrays.sort(intervals, new Comparator<int[]>() {
public int compare(int[] interval1, int[] interval2) {
return interval1[0] - interval2[0];
}
});
int n = intervals.length;
// 创建一个数组f,其中f[i]表示以第i个区间结尾的最长不重叠子序列的长度
int[] f = new int[n];
Arrays.fill(f, 1); // 初始时,每个区间自身就是一个长度为1的子序列
// 使用动态规划计算每个区间的最长不重叠子序列长度
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
// 如果第j个区间的结束时间小于等于第i个区间的起始时间,则第i个区间可以接在第j个区间后面
if (intervals[j][1] <= intervals[i][0]) {
// 更新f[i]为以第i个区间结尾的最长不重叠子序列的长度
f[i] = Math.max(f[i], f[j] + 1);
}
}
}
// 计算最长的不重叠子序列的长度
int maxNonOverlap = Arrays.stream(f).max().getAsInt();
// 返回总区间数减去最长不重叠子序列的长度,即为最少需要删除的区间数
return n - maxNonOverlap;
}
}
解题思路
-
边界情况:
- 如果输入的区间数组为空,直接返回0,因为没有区间需要处理。
-
排序:
- 将区间数组按区间的起始时间进行排序。这一步是为了方便后续动态规划的处理,使得在处理每个区间时,之前的区间都已经被处理过。
-
动态规划:
- 使用动态规划来解决这个问题。
f[i]
表示以第i
个区间结尾的最长不重叠子序列的长度。 - 初始时,每个区间自身就是一个长度为1的子序列,因此将
f
数组初始化为全1。 - 对于每一个区间
i
,遍历之前的所有区间j
。如果区间j
的结束时间不超过区间i
的起始时间,说明区间i
可以跟在区间j
后面,更新f[i]
的值为f[j] + 1
的最大值。
- 使用动态规划来解决这个问题。
-
计算结果:
- 找到
f
数组中的最大值,这个值表示最长的不重叠子序列的长度。 - 最少需要删除的区间数即为总区间数减去最长不重叠子序列的长度。
- 找到
时间复杂度
- 排序:
O(N log N)
,其中N
是区间数组的长度。 - 动态规划:
O(N^2)
,由于内层循环对每个区间执行一次。
总的时间复杂度是 O(N^2)
,适用于中等规模的数据。