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?
题意:
有个数据流每次提供一个数字,然后根据数据流组成一系列分离的区间
思路:
1、每进来一个新的数字val,我们都生成一个新的区间[val, val],然后将其插入到当前的区间里,注意分情况讨论,无重叠,相邻,和有重叠分开讨论处理:
class SummaryRanges {
public:
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e) : start(s), end(e) {}
};
SummaryRanges() {}
void addNum(int val) { //每插入一个元素就要遍历一遍所有的区间,分重叠,相邻,有重叠情况分别处理
Interval cur(val, val);
vector<Interval> res;
int pos = 0;
for (auto a : v) {
if (cur.end + 1 < a.start) {//无重叠且在cur后,直接插入
res.push_back(a);
} else if (cur.start > a.end + 1) {//无重叠且在cur前,直接插入,并将pos+1,pos为cur最后将插入的位置
res.push_back(a);
++pos;
} else if (cur.start - 1 == a.end) {//相邻且在cur前,则和cur合并,将cur.start置为a.start
cur.start = a.start;
} else if (cur.end + 1 == a.start) {//相邻且在cur后,则和cur合并,将cur.end置为a.end
cur.end = a.end;
} else {//重叠也将两者合并,start和end分别取max,min
cur.start = min(cur.start, a.start);
cur.end = max(cur.end, a.end);
}
}
res.insert(res.begin() + pos, cur);//插入cur
v = res;
}
vector<Interval> getIntervals() {
return v;
}
private:
vector<Interval> v;
};
2、二分搜索树
在每个结点中设置一个变量range来保存区间,当新数据val到来时,中序遍历整个二叉树,如果val在root的range中则无需修改或添加结点,直接返回。左相邻则修改start然后找到左子树最靠右的结点观察是否需要合并。右相邻则修改end然后找到右子树最靠左的结点观察是否需要合并。不相邻则分大小分别向左,向右遍历子树。
//存在不平衡的问题
struct MMTreeNode
{
Interval range;
MMTreeNode *left;
MMTreeNode *right;
MMTreeNode(int s, int e):range(s, e), left(NULL), right(NULL){}
};
class SummaryRanges {
private:
MMTreeNode *rt;
public:
SummaryRanges() {
rt = NULL;
}
void addNum(int val) {
addNumHelper(val, rt);
}
void addNumHelper(int val, MMTreeNode *&root)
{
if(root == NULL)
{ //处理第一个结点
root = new MMTreeNode(val, val);
return;
}
//如果val在root的区间之内,直接返回
if(root->range.start <= val && root->range.end >= val) return;
if(root->range.start == val + 1)
{
root->range.start = val;
//find the rightest node on the left subtree
if(root->left)
{
MMTreeNode *node = root->left;
if(node->right == NULL)
{
//右子树不存在,即左边第一个range的end==val-1,合并,删除,返回
if(node->range.end == val - 1)
{
root->range.start = node->range.start;
root->left = node->left;
delete node;
}
return;
}
//右子树存在,则找到最右的结点,(即root左子树中最大range)
MMTreeNode *parent;
while(node->right)
{
parent = node;
node = node->right;
}
if(node->range.end == val - 1) //若最右的range的end==val-1,合并,删除,返回
{
parent->right = node->left;
root->range.start = node->range.start;
delete node;
}
}
return;
}else if(root->range.end == val - 1)
{
root->range.end = val;
//找到右子树中最左的结点
if(root->right)
{
MMTreeNode *node = root->right;
if(node->left == NULL)
{
//如果左子树不存在,则找到的子树的根节点即为最左的结点
if(node->range.start == val + 1)
{
root->range.end = node->range.end;
root->right = node->right;
delete node;
}
return;
}
//如果左子树存在,则找到左子树中最左的结点
MMTreeNode *parent = root;
while(node->left)
{
parent = node;
node = node->left;
}
if(node->range.start == val + 1)
{
parent->left = node->right;
root->range.end = node->range.end;
delete node;
}
}
return;
}else if(root->range.start > val) //与start,end都不相邻的情况,小于start
{
addNumHelper(val, root->left);
}else //与start,end都不相邻的情况,大于end
{
addNumHelper(val, root->right);
}
}
vector<Interval> getIntervals() {
vector<Interval> result;
getIntervalsHelper(rt, result);
return result;
}
//中序遍历所有结点,将每个结点的range保存到result中
void getIntervalsHelper(MMTreeNode *root, vector<Interval> &result)
{
if(root == NULL) return;
getIntervalsHelper(root->left, result);
result.push_back(root->range);
getIntervalsHelper(root->right, result);
}
};