[LeetCode] 1288. Remove Covered Intervals
Given an array intervals
where intervals[i] = [li, ri]
represent the interval [li, ri)
, remove all intervals that are covered by another interval in the list.
The interval [a, b)
is covered by the interval [c, d)
if and only if c <= a
and b <= d
.
Return the number of remaining intervals.
Example 1:
Input: intervals = [[1,4],[3,6],[2,8]] Output: 2 Explanation: Interval [3,6] is covered by [2,8], therefore it is removed.
Example 2:
Input: intervals = [[1,4],[2,3]] Output: 1
Example 3:
Input: intervals = [[0,10],[5,12]] Output: 2
Example 4:
Input: intervals = [[3,10],[4,10],[5,11]] Output: 2
Example 5:
Input: intervals = [[1,2],[1,4],[3,4]] Output: 1
Constraints:
1 <= intervals.length <= 1000
intervals[i].length == 2
0 <= intervals[i][0] < intervals[i][1] <= 10^5
- All the intervals are unique.
删除被覆盖区间。
给你一个区间列表,请你删除列表中被其他区间所覆盖的区间。
只有当 c <= a 且 b <= d 时,我们才认为区间 [a,b) 被区间 [c,d) 覆盖。
在完成所有删除操作后,请你返回列表中剩余区间的数目。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-covered-intervals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题意是给一些 intervals,以 arrays of arrays 表示,给你一个区间列表,请你删除列表中被其他区间所覆盖的区间。
这里我给出一个图示,帮助理解。题意要求只有类似这样的 [c, d) 才能完全覆盖 [a, b),从而我们可以只保留 [c, d)。
/*[c, d)[a, b)[1, 10)[1, 5)[1, 3)*/
这道题依然是扫描线类型的题目,那么思路无非是对 start 排序或者是对 end 排序。这道题需要对 start 和 end 都要排序。先对 start 按升序排序,目的是把 start 较小的 interval 放在前面,那么 start 在后的 interval 会比较好比较,方便删除;对 start 相同的 interval,我们按降序对 end 排序,这样 end 较大的在前 - 区间跨度大的在前。这里的逻辑是当 start 相同的时候,end 大的在前,先被遍历到,所以 end 小的也会很方便地被判断出来是否需要去掉。
这道题我提供两种做法,本质都是扫描线,区别在于 count 变量的定义。第一种方法这里代码中的 count 变量记录的是可以被保留下来的 interval 的数量。对于第一个 interval,因为他的 end 是跟 0 比较,所以第一个 interval 一定可以被保留。对于之后的每一个 interval,因为他的 start 一定不小于之前的 interval 的 start,也就是说从第二个 interval 开始,每个 interval 的左边界是被其他 interval 罩住了的(之前有一个 interval 的左边界更大/更左),所以如果当前这个 interval 的 end 大于之前的 prevEnd,则说明这是一个需要被保留的 interval。比如图示中给的例子,先遍历到 [1, 10),保留;再遍历到 [1, 5),因为 5 小于 10 所以这个区间可以丢弃;反之如果是一个比如 [2, 12) 的区间的话,因为和 [1, 10) 是有重叠部分的所以两者都需要保留。
时间O(nlogn)
空间O(1)
Java实现
1 class Solution { 2 public int removeCoveredIntervals(int[][] intervals) { 3 // start较小的在前 4 // end较大的在前 5 Arrays.sort(intervals, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]); 6 int count = 0; 7 int end = 0; 8 int prevEnd = 0; 9 for (int[] cur : intervals) { 10 end = cur[1]; 11 if (prevEnd < end) { 12 count++; 13 prevEnd = end; 14 } 15 } 16 return count; 17 } 18 }
第二种方法代码中代码中的 count 变量记录的是需要被去掉的 interval 的数量,排序方式同方法一。时间空间复杂度相同。注意第 12 行,如果当前区间的end <= prevEnd,这就相当于是例子中的 b 遇到了 d,[a, b) 就需要被去掉。
Java实现
1 class Solution { 2 public int removeCoveredIntervals(int[][] intervals) { 3 // start较小的在前 4 // end较大的在前 5 Arrays.sort(intervals, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]); 6 int count = 0; 7 int prevEnd = 0; 8 int end = 0; 9 int len = intervals.length; 10 for (int[] cur : intervals) { 11 end = cur[1]; 12 if (end <= prevEnd) { 13 count++; 14 continue; 15 } 16 prevEnd = end; 17 } 18 return len - count; 19 } 20 }