352. Data Stream as Disjoint Intervals


June-20-2019

以前做的有问题,感觉遇到重复的会错,但是parameter变了,不好测了= =

这个题还是值得记一下的。其实是插入多个[1,1]这种interval。无非是跟前后判断就那么几种情况:

  • 左右相连,那一起MREGE,然后删掉后面的
  • 只和一边连,
  • 都不连
  • 其中一边囊括,

更重要等是一些general java 的相关

TreeMap

  • Key是排序的,可自定义comparator
  • lowerKey(), higherKey() 返还上一个,下一个存在的key
  • get(), remove(), containsKey(), lowerKey(), higherKey()都是O(lgN)

Stream

  • toArray(int[][]::new)

addNum: O(lgN) 做了好几次lgN: containsKey, lowerKey, higherKey, get()都是lgN

getInterval: O(N) 取决于最后有多少个interval

class SummaryRanges {  
    TreeMap<Integer, int[]> map;
    /** Initialize your data structure here. */
    public SummaryRanges() {
        map = new TreeMap<>();
    }
    
    public void addNum(int val) {
        if (map.containsKey(val)) return;
        Integer prevKey = map.lowerKey(val);
        Integer nextKey = map.higherKey(val);

        if (prevKey != null && map.get(prevKey)[1] + 1 == val
           && nextKey != null && map.get(nextKey)[0] - 1 == val) {
            map.get(prevKey)[1] = map.get(nextKey)[1];
            map.remove(nextKey);
        } else if (prevKey != null && map.get(prevKey)[1] + 1 == val) {
            map.get(prevKey)[1] = val;
        } else if (nextKey != null && map.get(nextKey)[0] - 1 == val) {
            map.put(val, new int[]{val, map.get(nextKey)[1]});
            map.remove(nextKey);
        } else if (prevKey != null && map.get(prevKey)[1] >= val){
            return;
        } else {
            map.put(val, new int[]{val, val});
        }
        
    }
    
    public int[][] getIntervals() {
        return map.entrySet()
           .stream()
           .map(entry -> new int[]{entry.getValue()[0], entry.getValue()[1]})
           .toArray(int[][]::new); 

    }
}

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * int[][] param_2 = obj.getIntervals();
 */

Follow up: What if there are lots of merges and the number of disjoint intervals are small compared to the data stream's size?

lots of merges说得很隐晦,其实指的是,很多次的进行add() -> 需要addNum()快一些。
log(n)已经很快了。。不知道怎么提速
然后最后interval少, getInterval()的 O(N)里N代表多少个区间,也很小,正好。。

(FB) 脸家给的follow-up是,addInterval(),不再是[2,2]这种,可以是[2,6]
楞做的话就 treeMap按照start排序
分情况

  • 完全包含在现有区间->无视
  • 完全不包含->加入新区间
  • 连接前后2个区间 -> merge
  • 和前后其中1个包含 -> 前后merge
  • 包含好几个现有区间 -> 最小start,最大end

仔细想想也挺麻烦。。

原文地址:https://www.cnblogs.com/reboot329/p/5891304.html