352. 将数据流变为多个不相交区间
给你一个由非负整数 a1, a2, ..., an
组成的数据流输入,请你将到目前为止看到的数字总结为不相交的区间列表。
实现 SummaryRanges
类:
SummaryRanges()
使用一个空数据流初始化对象。void addNum(int val)
向数据流中加入整数val
。int[][] getIntervals()
以不相交区间[starti, endi]
的列表形式返回对数据流中整数的总结。
示例:
输入:
["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]]
提示:
0 <= val <= 104
- 最多调用
addNum
和getIntervals
方法3 * 104
次
**进阶:**如果存在大量合并,并且与数据流的大小相比,不相交区间的数量很小,该怎么办?
题解:
我这里借鉴的是LeetCode的第56题合并区间问题的思想,题设要求我们将数字分为不想交的区间,则我们定义一个内部元素为长度为2的一维数组的List集合,取名为list,用它来保存每一个新增的区间,同时在getIntervals方法结束以后,更新其内容。
在**addNum(int val)**方法中:
我们选择的直接将**[val,val]**这样的区间添加到list集合中去
在**getIntervals()**方法中:
我们首先判断此时list集合是否为空:
- 如果为空,则表示此时list集合一个区间都没有添加,则直接返回空集即可
- 如果不为空,则我们定义一个新的结果集res,和list相同,同样为内部元素为长度为2的List集合,用其来存储不相交的结果集
- 首先我们需要对list集合进行排序,按照区间的start值进行从小到大的排序
- 然后我们依次取出list集合中的start和end的值,和前一个区间进行比较,如果满足能够合并的条件,则进行合并,然后将新的合并后的区间添加到res结果集中
- 最后将list指向此时的res集合,并且将res以二维数组的形式进行返回
示例的执行流程图如下所示:
代码实现:
class SummaryRanges {
List<int[]> list;
public SummaryRanges() {
list = new ArrayList<>();
}
public void addNum(int val) {
list.add(new int[]{val,val});
}
public int[][] getIntervals() {
if (!list.isEmpty()) {
List<int[]> res = new ArrayList<>();
Collections.sort(list,(o1,o2) -> o1[0] - o2[0]);
for (int i = 0; i < list.size(); i++) {
//获取当前排序后第i个区间的开始和结束值
int start = list.get(i)[0],end = list.get(i)[1];
if (res.size() == 0 || res.get(res.size() - 1)[1] < start - 1) {
res.add(new int[]{start,end});
}else {
res.get(res.size() - 1)[1] = Math.max(res.get(res.size() - 1)[1],end);
}
}
list = res;
return list.toArray(new int[list.size()][]);
}
return new int[0][2];
}
}
n list.toArray(new int[list.size()][]);
}
return new int[0][2];
}
}