Algorithm/src/main/java/range/EraseOverlapIntervals.java
2025-10-15 20:25:53 +08:00

75 lines
3.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}