题目地址:
https://www.lintcode.com/problem/time-intersection/description
给定两列区间,第一列代表用户 A A A的在线的起始和终止时间,第二列代表用户 B B B的在线的起始和终止时间。题目保证同一个用户的在线时间区间之间没有重叠。要求返回所有两个用户同时在线的时间对应的区间。
思路是扫描线。先将所有起始和终止时间点包装成一个Pair类,里面存两个变量,第一个变量代表时间,第二个变量代表”上线“还是”下线“,用 0 0 0代表下线,用 1 1 1代表上线(这主要是为了排序方便)。先将两个用户的所有的起始终止时间包装的Pair排序,时间前者优先,时间相同则下线者优先。接下来遍历这些Pair,同时用一个变量count记录当前在线人数。显然遇到了上线,count就加 1 1 1,否则减 1 1 1。当count等于 2 2 2的时候,说明两人同时在线了,此时加入一个区间到答案里去,其起始时间是可以确定的,但是其右端点确定不了,以待更新。为了区分count等于 1 1 1是从 0 0 0变过来的还是 2 2 2变过来的,我们开一个变量专门记录count变为 1 1 1之前的是否是 2 2 2(也就是开一个变量记录两个人同时在线的状态)。如果是,说明两个人有一个下线了,那么就更新区间的右端点。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
class Pair {
int time, flag;
public Pair(int time, int flag) {
this.time = time;
this.flag = flag;
}
}
/**
* @param seqA: the list of intervals
* @param seqB: the list of intervals
* @return: the time periods
*/
public List<Interval> timeIntersection(List<Interval> seqA, List<Interval> seqB) {
// Write your code here
List<Interval> res = new ArrayList<>();
List<Pair> list = new ArrayList<>();
// 将所有区间的端点加入list
for (Interval interval : seqA) {
list.add(new Pair(interval.start, 1));
list.add(new Pair(interval.end, 0));
}
for (Interval interval : seqB) {
list.add(new Pair(interval.start, 1));
list.add(new Pair(interval.end, 0));
}
// 将所有Pair排序。时间前者优先,时间相同则下线优先
list.sort((i1, i2) -> i1.time != i2.time ? Integer.compare(i1.time, i2.time) : Integer.compare(i1.flag, i2.flag));
// count记录在线人数
int count = 0;
// begin记录两个人开始在线的状态
boolean begin = false;
for (Pair cur : list) {
if (cur.flag == 1) {
count++;
} else {
count--;
}
// 如果在线时间达到两人,那就new一个区间加进res,并标记begin为true
if (count == 2) {
res.add(new Interval(cur.time, cur.time));
begin = true;
}
// 如果在线时间是一人,但是begin是true,说明是其中有一个人下线了,那么下线时间就是区间右端点
if (count == 1 && begin) {
res.get(res.size() - 1).end = cur.time;
// 标记两人同时在线为false
begin = false;
}
}
return res;
}
}
class Interval {
int start, end;
public Interval(int start, int end) {
this.start = start;
this.end = end;
}
}
时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n), n n n是区间总个数。