package range; import java.util.Arrays; /** * 题目: 435. 无重叠区间 (eraseOverlapIntervals) * 描述:给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。 * * 注意 只在一点上接触的区间是 不重叠的。例如 [1, 2] 和 [2, 3] 是不重叠的。 * 示例 1: 输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。 * 链接:https://leetcode.cn/problems/non-overlapping-intervals/ */ //不会 //二刷不会 //三刷不会 public class EraseOverlapIntervals { /** * 1.按结束时间排序 * 对所有区间按它们的右端点(end)从小到大排序。 * 这样,我们每次选取能最早「结束」的区间,就能给后面留下最大的空间,容纳更多不重叠的区间。 * * 2.一次线性扫描,维护「当前结束」 * 用变量 end 记录上一次加入的(未移除的)区间的结束位置,初始化为排序后第一个区间的结束。 * 用 count 记录当前保留下来的不重叠区间数量,初始化为 1(第一个区间肯定留下)。 * 从第二个区间开始遍历: * 如果当前区间的起点 start ≥ end,说明它与上一次保留的区间不重叠,可以「保留」: * count++,并更新 end = 当前区间的 end。 * 否则,它与上一次保留的区间发生重叠,必须移除其中一个。 * 为了让后续更容易接上,我们应当移除「结束得更晚」的那个区间,也就是保留结束更早的那个(即当前排序中的那个已经在保留的区间),此时不更新 end,相当于跳过(移除)当前区间。 * * 3.计算需移除的数量 * 最终保留下来的区间数为 count,总区间数为 n,所以最少要移除 n - count 个。 * @param intervals * @return */ public int eraseOverlapIntervals(int[][] intervals) { //0,3 2,5 4,7 int n = intervals.length; if (n == 0) { // 没有区间,当然不需要移除 return 0; } // 1. 按照区间的结束时间(end)从小到大排序 Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1])); // 2. 初始化:保留第一个区间 int count = 1; // 当前保留的不重叠区间数量 int end = intervals[0][1]; // 最近一次保留区间的结束时间 // 3. 遍历其余区间 for (int i = 1; i < n; i++) { int startI = intervals[i][0]; int endI = intervals[i][1]; if (startI >= end) { // 不重叠:可以保留 count++; end = endI; // 更新「最近一次保留区间」的结束时间 } // 否则:重叠。移除「结束更晚」的那个区间。 // 因为我们是按 end 升序遍历的,当前 intervals[i] 的 end ≥ end, // 所以移除它即可;无需更新 end。 } // 4. 最少移除数 = 总数 - 保留下来的数量 return n - count; } }