「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」
56. 合并区间
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
提示:
- 1 <= intervals.length <= 10^4
- intervals[i].length == 2
- 0 <= starti <= endi <= 10^4
排序+遍历比较相邻的交集情况
思路 这道题目是要让我们把有重叠的部分的数组进行合并,那么我们来看一下重叠的情况有几种
假设拥有两数组 [a,b] [c,d]
存在交集的可能如下:
- a>=c&&a<=d a大于等于c并且a小于等于d
- b>=c&&b<=d b大于等于c并且b小于等于d
- c>=a&&c<=b c大于等于a并且c小于等于b
- d>=a&&c<=b d大于等于a并且c小于等于b
那么不存在交集的情况呢?
- a>d a大于d那么一定不存在交集
- c>b c大于b也一定不存在交集
由上可得两个数组交集和不存在交集的所有情况,但是题目中的数组没有顺序,我们没办法保证相邻的不重叠,就不会与其他数组重叠,所以我们需要先排序,我们希望数组的0位按照从小到大的顺序进行排列,这里直接用sort完成排序
接下来,排序完毕后,我们得知,c必然大于等于a,所以只要c大于d那么一定不存在交集,否则存在交集
具体实现:
- 先对数组进行排序,以每一项的[0]位为基准
- 声明pre(上一个元素)为数组的第一个元素intervals[0]
- 从1开始遍历数组,判断相邻两个数组是否存在交集
- 如果不存在交集,则直接将pre放入结果res中
- 如果存在交集则合并两个数组,取两数组0位的最小值和1位的最大值组成新的数组,保存在pre中
- 循环完毕将pre中的最后一位放入res中 返回res即可
var merge = function (intervals) {
var res = [];
// 以item[0]为基准排序
intervals.sort((a, b) => {
return a[0] - b[0]
})
// pre 初始值
var pre = intervals[0];
for (var i = 1; i < intervals.length; i++) {
var item = intervals[i];
// [1,5] [2,6]
// 交集的情况 比较多
// [a,b] [c,d]
// a或者b 大于等于c并且小于等于d
// c或者d 大于等于a并且小于等于b
// 不交集的情况 就一种
// [a,b] [c,d]
// a>d 或者 c>b
// 但是数组不是有序的啊 所以先排序
if (item[0] > pre[1]) {
res.push(pre);
pre = item
} else {
pre[0] = Math.min(pre[0], item[0])
pre[1] = Math.max(pre[1], item[1])
}
}
if (pre) {
res.push(pre)
}
return res
};