LeetCode刷题之数据流的不相交区间

142 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

题目描述

给你一个由非负整数 a1, a2, ..., an 组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表。

实现 SummaryRanges 类:

  • SummaryRanges() 使用一个空数据流初始化对象。
  • void addNum(int val) 向数据流中加入整数 val
  • int[][] getIntervals() 以不相交区间 [starti, endi] 的列表形式返回对数据流中整数的总结。

示例1 :

输入:

["SummaryRanges", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals"] [[], [1], [], [3], [], [7], [], [2], [], [6], []]

输出:

[null, null, [[1, 1]], null, [[1, 1], [3, 3]], null, [[1, 1], [3, 3], [7, 7]], null, [[1, 3], [7, 7]], null, [[1, 3], [6, 7]]]

解释:

SummaryRanges summaryRanges = new SummaryRanges(); summaryRanges.addNum(1); // arr = [1] summaryRanges.getIntervals(); // 返回 [[1, 1]] summaryRanges.addNum(3); // arr = [1, 3] summaryRanges.getIntervals(); // 返回 [[1, 1], [3, 3]] summaryRanges.addNum(7); // arr = [1, 3, 7] summaryRanges.getIntervals(); // 返回 [[1, 1], [3, 3], [7, 7]] summaryRanges.addNum(2); // arr = [1, 2, 3, 7] summaryRanges.getIntervals(); // 返回 [[1, 3], [7, 7]] summaryRanges.addNum(6); // arr = [1, 2, 3, 6, 7] summaryRanges.getIntervals(); // 返回 [[1, 3], [6, 7]]

思路:hashMap+链表

分析:套用上链表,在用排序哈希表维护一个每个不相交区间的边界,即左边界对应最小值,右边界对应最大值。

class SummaryRanges {
    static class Node {
        int val;
        Node next;
    }
    static class IntervalNode {
        int start;
        int end;
        IntervalNode next;
    }

    Node node;

    public SummaryRanges() {
    }

    public void addNum(int val) {
        if (node == null) {
            // 添加第一个节点
            node = new Node();
            node.val = val;
            return;
        } else if (node.val > val) {
            // 小于第一个节点数字,作为首节点插入
            Node firstNode = new Node();
            firstNode.val = val;
            firstNode.next = node;
            node = firstNode;
            return;
        } else if (node.val == val) {
            // 与首节点相等
            return;
        }
        Node curNode = node;
        while (curNode.next != null) {
            if (curNode.next.val == val) {
                // 与当前节点相等
                return;
            } else if (curNode.next.val > val) {
                // 如果下一个节点数字比插入数字大,在当前节点后面插入节点
                Node node = new Node();
                node.val = val;
                node.next = curNode.next;
                curNode.next = node;
                return;
            } else {
                curNode = curNode.next;
            }
        }
        // 数字最大,添加到最后一个节点
        Node newNode = new Node();
        newNode.val = val;
        curNode.next = newNode;
    }

    public int[][] getIntervals() {
        if (node == null) {
            return null;
        }
        Node curNode = node;
        int length = 1;
        IntervalNode intervalNode = new IntervalNode();
        intervalNode.start = curNode.val;
        intervalNode.end = curNode.val;
        IntervalNode curIntervalNode = intervalNode;
        while ((curNode = curNode.next) != null) {
            if (curNode.val == curIntervalNode.end + 1) {
                curIntervalNode.end = curNode.val;
            } else {
                IntervalNode next = new IntervalNode();
                next.start = curNode.val;
                next.end = curNode.val;
                curIntervalNode.next = next;
                length++;
                curIntervalNode = curIntervalNode.next;
            }
        }
        int[][] ints = new int[length][2];
        IntervalNode copyNode = intervalNode;
        for (int i = 0; i < length; i++) {
            ints[i] = new int[]{copyNode.start, copyNode.end};
            copyNode = copyNode.next;
        }
        return ints;
    }
}