【352困难】将数据流变为多个不相交区间(2021.10.9)
1. 问题描述
给你一个由非负整数 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
次
2. 解题思路(并查集)
x表示区间的低位,find(x)表示区间的高位
- 提前将未被访问的x初始化为-1
- 当插入val时,先判断val的高位是什么,如果为-1表示原来没有添加过-1,将其高位置为val
- 判断val-1是否被添加过,如果存在,将val-1的高位连接到val
- 然后,判断val+1是否存在,如果存在,将val的高位连接到val+1的高位
- 同时使用了路径压缩的优化方法
3. 代码
class SummaryRanges {
public:
array<int, 10002> buff{0};
int max = -1;
// 注意遍历方式
void init(){
for(auto &i: buff) {
i = -1;
}
}
// 并查集中的查询函数
int find(int x) {
if(x < 0 || buff[x] == -1) {
return -1;
}
return buff[x] == x ? x : (buff[x] = find(buff[x]));
}
// 并查集中的合并函数
void quickLink(int x) {
if(find(x) == -1) {
buff[x] = x;
}
if(find(x-1) != -1) {
buff[x-1] = x;
}
if(find(x+1) != -1) {
buff[x] = buff[x+1];
}
}
SummaryRanges() {
init();
}
void addNum(int val) {
quickLink(val);
if(val > max) {
max = val;
}
}
vector<vector<int>> getIntervals() {
int x = 0, fx = 0;
vector<vector<int>> result;
while(x <= max) {
fx = find(x);
if(fx == -1) {
x++;
} else {
result.push_back( vector<int>{x,fx} );
x = fx + 1;
}
}
return result;
}
};
/**
* Your SummaryRanges object will be instantiated and called as such:
* SummaryRanges* obj = new SummaryRanges();
* obj->addNum(val);
* vector<vector<int>> param_2 = obj->getIntervals();
*/