7/5, Interval 类,扫描线
7/5, Interval 类,扫描线
Interval 类问题中最常用的技巧,就是自定义 IntervalComparator,把输入按照 startTime 升序排序。
对于任意两个区间A与B,如果
按 start 排序后,数组有了单调性,上面的判断条件就简化成了 A.end > B.start 则一定重叠.
排序后的 Interval 扫描过程中,为了保证正确性,要格外小心多个 Interval 在同一 x 时,处理的先后顺序,比如 skyline problem.
熟悉下 TreeMap 的常用 API.
另一个 fb onsite 面经题里,首先给 n 个一维 interval,返回任意重合最多的点;然后给 n 个二维 rectangle,返回任意重复最多的点。
扫描线算法。需要注意的是如果有两个 interval 首尾相接,要把结束的那个排在 array 的前面,先把房间腾出来;否则的话会认为收尾相接的两个 meeting 需要占 2 个房间,这是错误的。
(FB) follow-up: 如何返回重叠最多的那个区间?

这题需要注意的 corner case 有两个:
时间复杂度 O(n log n ) + O(n)
如果要进行进一步优化,要利用原题中 set of "non-overlapping" intervals 的条件,所以 newInterval 有可能会与任何 interval 或 N 个 interval 的集合,在左右两边 merge [0, N] 个 interval, 从完全 disjoint 到完全合并。
时间复杂度 O(n),one-pass.
在此基础上还可以进一步优化,不用额外空间,on-the-fly 解决战斗。
这种做法可以不花费任何额外空间,但是时间复杂度会更高,因为 List.remove() 是一个 O(n) 操作,add(index, val) 也是 O(n) 的。
如果实现代码的时候发现要写很多 if else 处理特殊情况,最好的选择还是暂停一下,多把 test case 思考全再动手。
时间复杂度 O(n).
addNum(int val) 时间复杂度 O(log n) + O(n)
getInterval() 时间复杂度 O(1)
空间复杂度 O(n)
n = 当前有效数字个数
在测试数据集上,这个方法和 TreeMap 的做法用时不相上下。
addNum(int val) 时间复杂度 O(n);
getIntervals() 时间复杂度 O(n);
空间:O(n);
n = 当前的有效数字个数。
参考了论坛代码之后,另一种巧妙的做法:
addNum(int val) 时间复杂度:O(log n)
getIntervals() 时间复杂度:o(n log n)
空间复杂度: O(n)
(FB) 给定的是 stream of intervals,求 cover range.
于是我觉得这题用 TreeMap 比较和乎人性的做法是,TreeMap 只负责维护 sorted intervals,需要查询 coverage 的时候,直接 new ArrayList<>(treeMap.values()) 给导出来然后跑一遍 merge interval ..
或者,直接维护一个按照 start time 排好序的 disjoint list of intervals,然后每次新的 interval 过来的时候,就 in-place 扫一遍做 merge 好了~ 这样每次 insert O(N),getCoverage O(1)
TreeMap.
O(Edge 排序) + O(Edge 数 * (插入 / 删除 + 查找))
O(2n log 2n) + O(2n * (log 2n + log 2n)) = O(n log n)
Last updated