【Lintcode】821. Time Intersection

题目地址:

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是区间总个数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值