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

 

扫描线相关题目

LeetCode 题目总结

posted @ 2020-10-05 04:08  CNoodle  阅读(612)  评论(0编辑  收藏  举报