leecode 解题总结:352. Data Stream as Disjoint Intervals

#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
};
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值