[LC352]Data Stream as Disjoint Intervals

352. Data Stream as Disjoint Intervals

Given a data stream input of non-negative integers a1, a2, …, an, …, summarize the numbers seen so far as a list of disjoint intervals.

For example, suppose the integers from the data stream are 1, 3, 7, 2, 6, …, then the summary will be:

[1, 1]

[1, 1], [3, 3]

[1, 1], [3, 3], [7, 7]

[1, 3], [7, 7]

[1, 3], [6, 7]

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

这是一道比较新的 hard 题目,刚到手会觉得十分繁琐,因为添加数字不是什么难事,困难的是每次需要查找是否存在 merge 的可能性,最直接的方法是看是否有添加的数字 num 的 num-1 或者 num+1的存在。

这方法毫无疑问需要起码 O(\(n^2)\)复杂度,对于大量数字的操作是不利的

根据提示我们了解到 Binary Search Tree是一个有效的方法,其基本过程如下

  1. 每个节点储存一个 interval
  2. 每次添加新的 num 时将会检查最近的一个 上限interval 和一个下限 interval 的数字,如果能够接上,则将接上 interval
  3. 删掉该节点,连接后续节点

因为 TreeMap 不是一个很常用的数据结构,我认为我们应该尽量少使用,多用基本的数据形式。

本方法由该页面作者启发,在此感谢

/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class SummaryRanges {
    class TreeNode{
        Interval val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int num){
            this.val = new Interval(num,num);
        }
    }

    TreeNode root;
    /** Initialize your data structure here. */
    public SummaryRanges() {

    }

    public void addNum(int val) {
         //假如不存在 root,那么新添加的数字将成为 root
        if(root == null) root = new TreeNode(val);
        else add(root,val);
        //其他情况检查是否存在 merge 的 interval
    }


    public void add(TreeNode root, int val){
        //恰好在某个 interval 范围内,不需要任何操作,直接返回
        if(root.val.start <= val && root.val.end>= val){
            return;
        }else if(root.val.start == val + 1){
        //如果 num 能够接上 root 当前的 start,那么扩展这个 interval,我们接下来需要查找的是最接近的一个 end 是否能让我们接上整个数字
            root.val.start = val;
            //now we need to see if child nodes has any merge
            TreeNode parent = root;
            TreeNode cur = root.left;
            while(cur != null && cur.right != null){
                parent = cur;
                cur = cur.right;
            }
            if(cur != null && (cur.val.end == root.val.start || cur.val.end +1 == root.val.start)){
                root.val.start = cur.val.start;
                if(parent == root){
                    parent.left = cur.left;
                }else{
                    parent.right = cur.left;
                }
            }
        }
        else if(root.val.end + 1 == val){
            root.val.end = val;
            TreeNode parent = root;
            TreeNode cur = root.right;
            while(cur != null && cur.left != null){
                parent = cur;
                cur = cur.left;
            }
            if(cur != null && (cur.val.start == root.val.end|| cur.val.start - 1 == root.val.end)){
                root.val.end = cur.val.end;
                if(parent == root){
                    parent.right = cur.right;
                }else{
                    parent.left = cur.right;
                }
            }
        }
        //此时我们无法对当前 root node 做任何操作,我们根据数字确定接下来要走的方向
        else if(root.val.start > val){
            if(root.left ==null ){
                root.left = new TreeNode(val);
            }else{
                add(root.left,val);
            }
        }

        else {
            if(root.right == null) root.right = new TreeNode(val);
            else{
                add(root.right,val);
            }
        }


    }

    public List<Interval> getIntervals() {
        List<Interval> res = new ArrayList();
        traverse(root,res);
        return res;
    }

    public void traverse(TreeNode root,List<Interval> res ){
        if(root != null){
            traverse(root.left,res);
            res.add(root.val);
            traverse(root.right,res);
        }
    }
}

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * List<Interval> param_2 = obj.getIntervals();
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值