【随笔】合并时间段的逻辑的整理

  我记得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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值