今天在博问中看到一个比较常见的问题: 求算法(合并重叠时间段)
在这里先把问题描述一下:
同一天中的一连串不连续时间段,合并其中重叠时间,如:
StartTime EndTime
06:10:58 08:15:28
07:38:56 10:34:45
10:55:00 11:34:00
13:09:34 17:45:23
14:23:12 15:24:14
16:14:25 17:52:15
...
合并后为:
StartTime EndTime
06:10:58 10:34:45
10:55:00 11:34:00
13:09:34 17:52:15
...
时间复杂度尽量避免n^2的情况,即集合内任一元素与其他元素各比较一次
StartTime EndTime
06:10:58 08:15:28
07:38:56 10:34:45
10:55:00 11:34:00
13:09:34 17:45:23
14:23:12 15:24:14
16:14:25 17:52:15
...
合并后为:
StartTime EndTime
06:10:58 10:34:45
10:55:00 11:34:00
13:09:34 17:52:15
...
时间复杂度尽量避免n^2的情况,即集合内任一元素与其他元素各比较一次
这样类似的问题很常见,下面把我的答案帖出来供大家拍砖,也欢迎大家提出更好的算法
代码:
public
class
bw22617
{
private List < Betime > timeList = new List < Betime > () {
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 10 , 55 , 0 ),EndTime = new DateTime( 2011 , 3 , 1 , 11 , 34 , 0 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 13 , 9 , 34 ),EndTime = new DateTime( 2011 , 3 , 1 , 17 , 45 , 23 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 14 , 23 , 12 ),EndTime = new DateTime( 2011 , 3 , 1 , 15 , 24 , 14 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 7 , 38 , 56 ),EndTime = new DateTime( 2011 , 3 , 1 , 10 , 34 , 45 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 6 , 10 , 58 ),EndTime = new DateTime( 2011 , 3 , 1 , 8 , 15 , 28 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 16 , 14 , 25 ),EndTime = new DateTime( 2011 , 3 , 1 , 17 , 52 , 15 )}
};
public void Union()
{
// 先对数据排序
timeList = timeList.OrderBy(p => p.BeginTime).ToList < Betime > ();
for ( int i = 0 ; i < timeList.Count - 1 ;i ++ )
{
int j = i + 1 ;
if (timeList[i].EndTime >= timeList[j].BeginTime)
{
// 处理后一条数据的结束时间比前一条数据结束时间小的情况
if (timeList[i].EndTime >= timeList[j].EndTime)
{
timeList[j] = timeList[i];
}
else
{
timeList[j].BeginTime = timeList[i].BeginTime;
}
timeList[i] = null ;
}
else
{
i ++ ;
}
}
timeList.ForEach(
delegate (Betime p)
{
if (p != null )
{
Console.WriteLine( " BeginTime: " + p.BeginTime + " \tEndTime: " + p.EndTime);
}
}
);
}
}
public class Betime
{
public DateTime BeginTime { get ; set ; }
public DateTime EndTime { get ; set ; }
}
{
private List < Betime > timeList = new List < Betime > () {
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 10 , 55 , 0 ),EndTime = new DateTime( 2011 , 3 , 1 , 11 , 34 , 0 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 13 , 9 , 34 ),EndTime = new DateTime( 2011 , 3 , 1 , 17 , 45 , 23 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 14 , 23 , 12 ),EndTime = new DateTime( 2011 , 3 , 1 , 15 , 24 , 14 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 7 , 38 , 56 ),EndTime = new DateTime( 2011 , 3 , 1 , 10 , 34 , 45 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 6 , 10 , 58 ),EndTime = new DateTime( 2011 , 3 , 1 , 8 , 15 , 28 )},
new Betime{BeginTime = new DateTime( 2011 , 3 , 1 , 16 , 14 , 25 ),EndTime = new DateTime( 2011 , 3 , 1 , 17 , 52 , 15 )}
};
public void Union()
{
// 先对数据排序
timeList = timeList.OrderBy(p => p.BeginTime).ToList < Betime > ();
for ( int i = 0 ; i < timeList.Count - 1 ;i ++ )
{
int j = i + 1 ;
if (timeList[i].EndTime >= timeList[j].BeginTime)
{
// 处理后一条数据的结束时间比前一条数据结束时间小的情况
if (timeList[i].EndTime >= timeList[j].EndTime)
{
timeList[j] = timeList[i];
}
else
{
timeList[j].BeginTime = timeList[i].BeginTime;
}
timeList[i] = null ;
}
else
{
i ++ ;
}
}
timeList.ForEach(
delegate (Betime p)
{
if (p != null )
{
Console.WriteLine( " BeginTime: " + p.BeginTime + " \tEndTime: " + p.EndTime);
}
}
);
}
}
public class Betime
{
public DateTime BeginTime { get ; set ; }
public DateTime EndTime { get ; set ; }
}
调用代码(很简单啦):
static
void
Main(
string
[] args)
{
bw22617 test = new bw22617();
test.Union();
Console.Read();
}
{
bw22617 test = new bw22617();
test.Union();
Console.Read();
}
结果:
欢迎大家提出更高效的算法啦!
非常感谢青龙白虎 的意见,经检查程序确实有问题,主要在第二条数据的结束时间比第一条数据的结束时间还小及数据未排序的时候,现已更改