题目链接:https://leetcode.com/problems/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?
思路:
建立一棵二叉搜索树,树的节点值用interval表示,其实就是类似于“区间树”节点值是个区间,这些区间不相交。建立树之后中序遍历输出结果。
插入的过程较为麻烦,插入需要考虑一个节点的两端点,情况较多,具体见代码注释。
插入时间复杂度为O(logn)。如果不用二查搜索树,直接用list做也可以,时间复杂度为O(n),leetcode也能ac。
算法:
public class SummaryRanges { Node root; /** Initialize your data structure here. */ public SummaryRanges() { } public void addNum(int val) { if (root == null) { Interval v = new Interval(val, val); root = new Node(v, null, null); } else { searchAndAdjust(root, val); } } /** * 搜索并调整树 */ public void searchAndAdjust(Node node, int val) { // 若插入val在树左边,插入并调整 if (node.val.start == val + 1) { // 若满足合并条件 node.val.start = val;// 修改区间 if (node.left != null) {// 调整左边 if (node.left.right == null) {// 若左孩子的右孩子为空 if (node.left.val.end + 1 == val) {// 若左孩子可以和父结点合并 node.val.start = node.left.val.start; node.left = node.left.left; } } else {// 若左孩子的右孩子不为空 Node tmp = node.left; Node parent = tmp; while (tmp.right != null) {// 一直走到node节点左孩子的最右节点 parent = tmp; tmp = tmp.right; } if (tmp.val.end + 1 == val) {// 若可以和根节点合并 node.val.start = tmp.val.start; parent.right = tmp.left; } } } return; } if (node.val.start > val + 1) { if (node.left == null) {// 无法合并区间时 新建节点 Interval v = new Interval(val, val); Node newNode = new Node(v, null, null); node.left = newNode; return; } else {// 进入下一层搜索 searchAndAdjust(node.left, val); } } // ======end // 若插入val在树右边,插入并调整,同上 if (node.val.end == val - 1) { node.val.end = val; if (node.right != null) { if (node.right.left == null) { if (node.right.val.start - 1 == val) { node.val.end = node.right.val.end; node.right = node.right.right; } } else { Node tmp = node.right; Node parent = tmp; while (tmp.left != null) {// 一直走到node节点左孩子的最右节点 parent = tmp; tmp = tmp.left; } if (tmp.val.start - 1 == val) {// 若可以和根节点合并 node.val.end = tmp.val.end; parent.left = tmp.right; } } } return; } if (node.val.end < val - 1) { if (node.right == null) { Interval v = new Interval(val, val); Node newNode = new Node(v, null, null); node.right = newNode; return; } else { searchAndAdjust(node.right, val); } } } public List<Interval> getIntervals() { List<Interval> res = new ArrayList<Interval>(); res = inorder(root, res); return res; } public List<Interval> inorder(Node node, List<Interval> res) { if (node != null) { res = inorder(node.left, res); res.add(node.val); res = inorder(node.right, res); } return res; } class Node { Interval val; Node left, right; public Node(Interval val, Node left, Node right) { this.val = val; this.left = left; this.right = right; } } }