中等
统计不重叠区间数量
数组排序区间
相关算法文章:
题目描述
给定一个二维数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi](starti 和 endi 都是整数)。这些区间之间可能存在重叠,请统计跟其他任何区间都不重叠的区间数量。
区间重叠判定: 两个区间 [a, b] 和 [c, d] 重叠,当且仅当一个区间的起点 ≤ 另一个区间的终点且另一个区间的起点 ≤ 该区间的终点。
数据范围:
- 1 ≤ intervals.length ≤ 10000
- intervals[i].length == 2
- 0 ≤ starti ≤ endi ≤ 10000
示例
示例1:
输入:[[8,10],[1,4],[2,6],[15,18]]
输出:2
说明:区间 [8,10] 和 [15,18] 跟其他区间都不重合。
示例2:
输入:[[2,4],[4,6]]
输出:0
说明:[2,4] 和 [4,6] 这 2 个区间重叠(在端点 4 处相接也算重叠),不存在跟其他区间都不重叠的区间,故返回 0。
解题思路
核心思路:排序 + 相邻检查
- 按起点排序:将所有区间按
start升序排列。 - 检查每个区间:对于排序后的第 i 个区间,只需检查它是否与相邻区间重叠:
- 与左边的区间 i-1 是否重叠:
list[i-1][1] >= list[i][0] - 与右边的区间 i+1 是否重叠:
list[i][1] >= list[i+1][0]
- 与左边的区间 i-1 是否重叠:
- 为什么只需检查相邻? 排序后,如果一个区间与不相邻的区间重叠,那么它必然也会与它们中间的某个相邻区间重叠。因此只需要检查直接相邻的区间即可。
代码实现
function getCount(list) {
// 按起点排序
list.sort((a, b) => a[0] - b[0]);
let c = 0;
for (let i = 0; i < list.length; i++) {
let overlap = false;
// 检查是否与右边区间重叠
if (i + 1 < list.length && list[i][1] >= list[i + 1][0]) {
overlap = true;
}
// 检查是否与左边区间重叠
if (i - 1 >= 0 && list[i - 1][1] >= list[i][0]) {
overlap = true;
}
if (!overlap) c++;
}
return c;
}
复杂度分析
- 时间复杂度: O(n log n),排序占主导,遍历检查为 O(n)。
- 空间复杂度: O(1),原地排序,只使用常数额外空间。
示例输入 / 输出
下面给出一组输入输出示例,便于对照题意与结果。
编号 non-overlapping-intervals难度 中等
输入
[[8,10],[1,4],[2,6],[15,18]]
输出
2