#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
using namespace std;
/*
问题:
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?
分析:题目是给定一个输入流,不断添加整数,要求返回该整数数组中的范围区间。
也就是每输入一个整数,需要更新区间。
最简单的方法:对于每输入一个整数i
1】如果已经有区间存在,寻找到整数i可以所属于的区间[m,n],判断如果m <= i <= n,则无需进行处理;
2】如果存在区间[m,n],并且有i=m-1,则将区间[m,n]替换为[m-1,n],然后扫描一遍区间,看是否可以合并区间。
3】如果存在区间[m,n],并且有i=n+1,则将区间[m,n]替换为[m,n+1],然后扫描区间,看是否可以合并区间。
4】如果不满足1】,2】,3】,则单独开辟一个区间[i,i]
合并区间:对于区间[m,n],
如果是2】的情况,判断[m,n]前面一个区间[p,q]中q是否为i-1,如果为i-1,则将这两个区间合并为[p,n]
如果是3】的情况,判断[m,n]后面一个区间[p,q]中的p是否为i+1,如果为i+1,则将这两个区间合并为[m,q]
需要对区间排序,时间复杂度为O(NlogN),每插入一个新额整数,寻找整数i所在的区间O(N),更新操作
时间为O(1),如果有N个数,总的 时间复杂度就是O(n^2)
输入:
5(数组元素个数)
1 3 7 2 6(各个元素)
3
1 9 2
输出:
[1, 1]
[1, 1], [3, 3]
[1, 1], [3, 3], [7, 7]
[1, 3], [7, 7]
[1, 3], [6, 7]
[1,1]
[1,1], [9,9]
[1,2], [9,9]
报错:
Runtime Error Message:
member call on null pointer of type 'const struct _Rb_tree_node'
Last executed input:
["SummaryRanges","addNum","getIntervals","addNum","getIntervals"]
[[],[1],[],[0],[]]
看错了isFirst弄错了
关键:
1一个简单的解法,首先尝试把当前区间[i,i]用lower_bound查找,找到该区间应该在的位置it,判断该区间
前一个位置+1,如果小于当前值,说明前一个区间不可能,迭代器it累加。
然后判断如果it->start <= val + 1 并且 val - 1 <= it->end,就删除当前区间,记录新的区间位置,
返回下一个区间判断,直至删除可合并的区间后,再插入新区间
2 最简单的方法:对于每输入一个整数i
1】如果已经有区间存在,寻找到整数i可以所属于的区间[m,n],判断如果m <= i <= n,则无需进行处理;
2】如果存在区间[m,n],并且有i=m-1,则将区间[m,n]替换为[m-1,n],然后扫描一遍区间,看是否可以合并区间。
3】如果存在区间[m,n],并且有i=n+1,则将区间[m,n]替换为[m,n+1],然后扫描区间,看是否可以合并区间。
4】如果不满足1】,2】,3】,则单独开辟一个区间[i,i]
合并区间:对于区间[m,n],
如果是2】的情况,判断[m,n]前面一个区间[p,q]中q是否为i-1,如果为i-1,则将这两个区间合并为[p,n]
如果是3】的情况,判断[m,n]后面一个区间[p,q]中的p是否为i+1,如果为i+1,则将这两个区间合并为[m,q]
*/
struct Interval {
int start;
int end;
Interval() : start(0), end(0) {}
Interval(int s, int e) : start(s), end(e) {}
};
//对区间排序,先对区间起点按从小到大排序,再按终点从小到大排序
struct Compare
{
bool operator()(const Interval& interval1 , const Interval& interval2)
{
if(interval1.start != interval2.start)
{
return (interval1.start < interval2.start);
}
else
{
return (interval1.end < interval2.end);
}
}
};
class SummaryRanges {
public:
/** Initialize your data structure here. */
SummaryRanges() {
}
void addNum(int val) {
//获取当前待插入区间的前一个区间
auto it = _intervals.lower_bound(Interval(val , val));
//判断前一个区间是否需要包含进来
if(it != _intervals.begin() && ((--it)->end + 1 < val) )
{
it++;
}
//尝试合并区间,必须满足当前值+1,当前值-1在区间内
int start = val;
int end = val;
while(it != _intervals.end() && it->start <= (val + 1) && (val - 1) <= it->end)
{
start = min(start , it->start);//更新待插入区间左右端点值
end = max(end , it->end);
it = _intervals.erase(it);
}
_intervals.insert(Interval(start , end));
}
vector<Interval> getIntervals() {
vector<Interval> result(_intervals.begin() , _intervals.end());
return result;
}
private:
set<Interval , Compare> _intervals;//需要每次插入区间的时候排好序,那么就要用set
};
void print(vector<Interval>& result)
{
if(result.empty())
{
cout << "no result" << endl;
return;
}
int size = result.size();
for(int i = 0 ; i < size ; i++)
{
cout << "[" << result.at(i).start << "," << result.at(i).end << "], " ;
}
cout << endl;
}
void process()
{
int value;
int num;
vector<Interval> result;
while(cin >> num )
{
SummaryRanges obj;
for(int i = 0 ; i < num ; i++)
{
cin >> value;
obj.addNum(value);
result = obj.getIntervals();
print(result);
}
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}
/*
//对区间排序,先对区间起点按从小到大排序,再按终点从小到大排序
struct Compare
{
bool operator()(const Interval& interval1 , const Interval& interval2)
{
if(interval1.start != interval2.start)
{
return (interval1.start < interval2.start);
}
else
{
return (interval1.end < interval2.end);
}
}
};
class SummaryRanges {
public:
SummaryRanges() {
}
void addNum(int val) {
if(_intervals.empty())
{
Interval interval(val ,val);
_intervals.insert(interval);
return;
}
//接下来要查找当前元素所属于的区间
set<Interval>::iterator previousIter;
bool isFirst = true;
set<Interval>::iterator nextIter = _intervals.begin();
nextIter++;
for(set<Interval>::iterator it = _intervals.begin() ; it != _intervals.end() ; it++)
{
//如果当前元素恰好在区间内,则无需处理
if(it->start <= val && val <= it->end)
{
return;
}
//如果元素i是当前区间末尾值加1,则修改当前区间
if(it->end == val - 1)
{
//判断其下一个区间是否需要合并
if(nextIter != _intervals.end())
{
//如果后一个区间需要合并
if(nextIter->start == val + 1)
{
//先修改当前区间,需要删除这两个区间
Interval newInterval(it->start , nextIter->end);
_intervals.erase(nextIter);
_intervals.erase(it);
_intervals.insert(newInterval);
}
//只需要合并前一个区间
else
{
Interval newInterval(it->start , val);
_intervals.erase(it);
_intervals.insert(newInterval);
}
}
//说明只需要修改前一个区间,当前区间无需修改
else
{
Interval newInterval(it->start , val);
_intervals.erase(it);
_intervals.insert(newInterval);
}
return;
}
//需要合并左边部分
if(it->start == val + 1)
{
//如果是首次,表明该区间没有前面的区间
if(isFirst)
{
Interval newInterval(val , it->end);
_intervals.erase(it);
_intervals.insert(newInterval);
}
//当前区间有前向区间
else
{
//需要合并前向区间
if(previousIter->end == val - 1)
{
Interval newInterval(previousIter->start , it->end);
_intervals.erase(it);
_intervals.erase(previousIter);
_intervals.insert(newInterval);
}
//无需合并前向区间
else
{
Interval newInterval(val , it->end);
_intervals.erase(it);
_intervals.insert(newInterval);
}
}
return;
}
previousIter = it;
if(nextIter != _intervals.end())
{
nextIter++;
}
isFirst = false;
}
//走到这里,说明没有产生区间,此时,单独开辟一个区间
Interval interval(val ,val);
_intervals.insert(interval);
}
vector<Interval> getIntervals() {
vector<Interval> result(_intervals.begin() , _intervals.end());
return result;
}
private:
set<Interval , Compare> _intervals;//需要每次插入区间的时候排好序,那么就要用set
};
*/
leecode 解题总结:352. Data Stream as Disjoint Intervals
最新推荐文章于 2020-06-12 12:22:46 发布