方法1:动态规划。类似于最长上升子序列问题。 时间复杂度为O(n^2), 空间复杂度:O(n)
先将所有的 n 个区间按照左端点从小到大进行排序,随后使用动态规划的方法求出区间数量的最大值。
☆☆☆☆方法2【最优解】:贪心算法。时间复杂度:O(nlogn), 空间复杂度:O(logn)
每次选择中,前一个区间的结尾越小,后面越有可能容纳更多区间。
两种思路,可以对区间尾进行排序,也可以对区间头排序。
代码1:
class Solution { public int eraseOverlapIntervals(int[][] intervals) { if (intervals.length == 0) { return 0; } // 对每个区间排序,以区间头的大小为参考 // Arrays.sort(intervals, new Comparator<int[]>() { // @Override // public int compare(int[] o1, int[] o2) { // return o1[0] - o2[0]; // 如果返回正数,说明o1[0] > o2[0],不符合升序,正数类比为true,表示需要调整顺序。 // } // }); Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]); // 状态的定义: dp[i]表示 从区间0开始,以区间i为最后一个区间,可以选出的区间数量的最大值。 // 初始化:把区间i单独拿出来就是1个互不重叠的区间,因此初始化为1 int[] dp = new int[intervals.length]; Arrays.fill(dp, 1); int res = 1; for (int i = 1; i < intervals.length; i++) { for (int j = 0; j < i; j++) { // 说明区间i可以跟在区间i后面 if (intervals[i][0] >= intervals[j][1]) { dp[i] = Math.max(dp[i], 1 + dp[j]); } } res = Math.max(res, dp[i]); // 所有dp[i]里取最大的 } return intervals.length - res; } }
代码2:
class Solution { public int eraseOverlapIntervals(int[][] intervals) { if (intervals.length == 0) { return 0; } /** * 方法1:按照区间头来排序,记录移除的次数 * 如果遇到覆盖,那么就需要删除一个区间,因为需要尽可能不与后面的区间产生重叠, * 应该让现有区间越短越好,因此需要移除尾部较大的,保留区间结尾较小的。 */ Arrays.sort(intervals, (o1, o2) -> o1[0] - o2[0]); int count = 0; // 移除的次数 int pre = 0; // 前一个区间的索引 for (int i = 1; i < intervals.length; i++) { // 如果发生重叠 if (intervals[i][0] < intervals[pre][1]) { count ++; // 更新保留的区间索引,保留尾部较小的那个 pre = intervals[pre][1] < intervals[i][1] ? pre : i; }else { pre = i; } } return count; /** * 方法2:按照区间尾来排序,记录选择区间的个数 * 每次选择结尾最早的,且和前一个区间不重叠的区间 */ /* Arrays.sort(intervals, (o1, o2) -> o1[1] - o2[1]); int res = 1; // 选择区间的个数 int pre = 0; for (int i = 1; i < intervals.length; i++) { if (intervals[i][0] >= intervals[pre][1]) { res ++; pre = i; } } return intervals.length - res; */ } }
【知识点补充】如何自定义排序规则为 升序 还是 降序 ?
设o1表示位于前面的元素,o2表示后面的元素。
如果想升序,对于o1-o2,如果结果为负数,说明o1 < o2,符合升序要求,负数类比为false,表示不需要调整顺序。
如果结果为正数,说明o1 > o2,不符合升序要求,正数类比为true,表示需要调整顺序。
如果想降序,对于o2-o1,如果结果为负数,说明o2 < o1,符合降序要求,负数类比为false,表示不需要调整顺序。
如果结果为正数,说明o2 > o1,不符合降序要求,正数类比为true,表示需要调整顺序。