【Lintcode】1280. Data Stream as Disjoint Intervals

题目地址:

https://www.lintcode.com/problem/1280/

要求设计一个数据结构,可以实现下面操作:
1、添加一个数;
2、得到已经添加的数形成的闭区间族,从小到大返回,要求连续的数要合并为一个区间,相邻区间至少中间要隔开一个数,并且区间两两不相交。

思路是利用TreeSet。这个TreeSet直接用来存区间。当添加一个数 x x x的时候,先去查一下右端点最大且小于等于 x x x的那个区间(即floor),和左端点最小且大于等于 x x x的那个区间(即ceiling),如果这两个区间都不能和 x x x合并,那就直接将单点区间 [ x , x ] [x,x] [x,x]加入进TreeSet;否则先将 x x x与俩区间进行合并,如果floor和ceiling得到的俩区间还能进一步合并,则删掉floor那个区间,然后更新ceiling的右端点(至于是删除floor更新ceiling,还是删除ceiling更新floor,这要看TreeSet的Comparator如何定义。如果TreeSet里的区间按照左端点排序的,那么就要删floor)。为了避免floor和ceiling得到null的麻烦,可以预先将正负无穷两个数的单点区间加入TreeSet。代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

public class Solution {
    
    private TreeSet<Interval> set = new TreeSet<>((i1, i2) -> Integer.compare(i1.start, i2.start));
    
    {
        set.add(new Interval(Integer.MIN_VALUE, Integer.MIN_VALUE));
        set.add(new Interval(Integer.MAX_VALUE, Integer.MAX_VALUE));
    }
    
    /**
     * @param val: An integer.
     * @return: nothing
     */
    public void addNum(int val) {
        // write your code here
        Interval interval = new Interval(val, val);
        Interval floor = set.floor(interval), ceiling = set.ceiling(interval);
        if (floor.end < val - 1 && ceiling.start > val + 1) {
            set.add(interval);
            return;
        }
        
        if (ceiling.start == val + 1) {
            ceiling.start = val;
        }
        if (floor.end == val - 1) {
            floor.end = val;
        }
    
        if (floor.end == ceiling.start) {
        	// 由于是按照左端点排序,所以要删floor。
        	// 注意TreeSet里删除的时候是调用的比较器判相等的
            set.remove(floor);
            ceiling.start = floor.start;
        }
    }
    
    /**
     * @return: A list of intervals.
     */
    public List<Interval> getIntervals() {
        // write your code here
        return new ArrayList<>(set).subList(1, set.size() - 1);
    }
}

class Interval {
    int start, end;
    
    public Interval(int start, int end) {
        this.start = start;
        this.end = end;
    }
}

添加时间复杂度 O ( log ⁡ n ) O(\log n) O(logn), n n n是已经得到的区间个数,得到全部区间 O ( n ) O(n) O(n),空间 O ( n ) O(n) O(n)。

上一篇:【Lintcode】1730. Spreadsheet Notation Conversion


下一篇:LintCode刷题——分割回文串Ⅱ(序列型动态规划)