Algorithm/src/main/java/range/EraseOverlapIntervals.java

75 lines
3.2 KiB
Java
Raw Normal View History

2025-05-27 09:57:47 +08:00
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/
*/
//不会
2025-09-23 20:55:16 +08:00
//二刷不会
2025-10-15 20:25:53 +08:00
//三刷不会
2025-05-27 09:57:47 +08:00
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;
}
}