我记得leetcode上好像有类似这个的题,那个解法应该更简洁,我这个就是梳理了一下逻辑然后记录下来,方便以后查看,大家如果发现问题,欢迎指正。话说用文本画图也挺方便的,还感觉挺好看的。
/*
问题背景: 从底层传回来了若干的时间段,每个时间段只知道开始时间和结束时间,这些时间段之间存在交集、包括、独立的关系
那么有交集的就把两个时间段合并,时间段A被别的时间段B包括,那么就删除A,
如果两个时间段相互独立(没有时间交集)那么就不处理。
需要我处理按照上面要求处理时间段。
思路: 假如有两个时间段t1[s1,e1], t2[s2,e2],要合并这两个时间段首先需要排序
[排序规则]先比较s1,s2,小的排在前面,如果s1==s2相同再比较e1,e2,小的排在前面,如果两个参数都相同则t1排在前面
排完序后,假设t1在前t2在后,开始合并
[合并规则]这里用图列出所有可能出现的条件,注意要谨记排序后s1、e1、s2、e2先天存在的大小关系
【s1<s2】
【e1 >= e2】
__________________
| _____ |
| | | |
| | | |(包括)
----------------------------------
s1 s2 e2 e1
____________
| _____|
| | |
| | |(包括)
----------------------------------
s1 s2 e2/e1
【e1 < e2】
【e1 >= s2】
__________________
| ___________|______
| | | |
| | | |(交集)
----------------------------------
s1 s2 e1 e2
__________________
| |______
| | |
| | |(交集)
----------------------------------
s1 e1/s2 e2
【e1<s2】
___________
| | ______
| | | |
| | | |(独立)
----------------------------------
s1 e1 s2 e2
【s1==s2】
【e1<=e2】(第四种情况 t1排在t2前面时,只能存在e1必须小于等于e2)
__________________
|__________________|______
| | |
| | |(包括)
----------------------------------
s1/s2 e1 e2
__________________
| |
| |
| |(包括)
----------------------------------
s1/s2 e1/e2
【s1>s2】 (t1排在t2前面则不存在此情况)
总结: 图画的不错,逻辑上应该没有问题,但是代码中模拟的随机时间段用例不好,时间太紧凑了,最后都合成了一段,实际情况应该是好几段的。
*/
#include <cstdio>
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <ctime>
#include <cstdlib>
using namespace std;
//调试区域
const int const_mintime = 0; //最小随机值
const int const_maxtime = 200; //最大随机值
const int const_testcount = 10; //测试时间段数量
// 获取随机时间 左闭右闭区间
int getRand(int min = const_mintime, int max = const_maxtime) {
return ( rand() % (max - min + 1) ) + min ;
}
//时间段结构体
class mytime{
public:
mytime(){
}
mytime(int s, int e) : m_stime(s),m_etime(e){
}
int m_stime;//开始时间
int m_etime;//结束时间
int m_index;
};
/*自定义比较函数,
先比较m_stime,m_stime小则排在前面,如果m_stime相同再比较m_etime,m_etime小则排在前面,
如果两个参数都相同则t1排在前面
*/
bool cmp (mytime t1, mytime t2) {
bool ret = false;
if(t1.m_stime < t2.m_stime){
ret = true;
}else if(t1.m_stime > t2.m_stime){
ret = false;
}else{
//当t1 t2 的m_stime相同时 继续判断m_etime
if(t1.m_etime < t2.m_etime){
ret = true;
}else if(t1.m_etime > t2.m_etime){
ret = false;
}else{
ret = true;
}
}
return ret;
}
//输出时间段
void OutputTimeSeg(list<mytime> & _list){
int count = 0;
auto iter = _list.begin();
while(iter != _list.end()){
(*iter).m_index = count;
cout<<"["<<count<<"]"<<" start="<<(*iter).m_stime<<" end="<<(*iter).m_etime<<endl;
iter++;
count++;
}
}
int main(){
//填充随机时间段
srand(time(0));
list<mytime> listtime;
for (int i=0; i<const_testcount; i++) {
mytime t1(0,0);
t1.m_stime = getRand();
while((t1.m_etime = getRand()) <= t1.m_stime){
//m_etime必须大于m_stime,否则就一直获取新的时间
}
listtime.push_back(t1);
}
//先将随机时间段排序
listtime.sort(cmp);
OutputTimeSeg(listtime);
//合并时间段,也就是讲两个有重叠的时间段合成一个时间段
//在一个循环中两两比较
auto iter = listtime.begin();
mytime t1 = *iter;
while(iter != --(listtime.end())){
mytime t2 = *(++iter);
cout<<"合并 t1 index="<<t1.m_index<<" t2 index="<<t2.m_index<<endl;
if(t1.m_stime < t2.m_stime){
if(t1.m_etime >= t2.m_etime){//包括
(*iter).m_stime = t1.m_stime;
(*iter).m_etime = t1.m_etime;
iter = listtime.erase(--iter);
}else if(t1.m_etime < t2.m_etime){
if(t1.m_etime >= t2.m_stime){//交集
(*iter).m_stime = t1.m_stime;
iter = listtime.erase(--iter);
}else if(t1.m_etime < t2.m_stime){//独立
}
}
}else if(t1.m_stime == t2.m_stime){
if(t1.m_etime <= t2.m_etime){//包括
iter = listtime.erase(--iter);
}
}
t1 = *iter;
}
cout<<"合并时间段后的结果 : "<<endl;
OutputTimeSeg(listtime);
return 0;
}