1.MyCalendar I
/*
//实现我的日历类,类里面有一个 Book(int start,int end)方法
//代表要添加一个代办事件,事件的时间区间,这个区间是半开区间[start,end),即左闭右开
//每次添加一个事件后,如果时间区间和已有的区间没有冲突则返回true,否则返回false
//eg:
* MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false
MyCalendar.book(20, 30); // returns true
*/
List<Interval> events = new List<Interval>();
private bool Book(int start, int end)
{
Interval interval = new Interval(start, end);
for (int i = 0; i < events.Count; i++)
{
if (interval.y <= events[i].x)
{
events.Insert(i, interval); //新添加的事件结束时间小于事件[i]的开始时间,可以添加成功
//将新事件添加到当前位置,使列表事件有序
return true;
}
if (interval.x < events[i].y) //新添加事件的时间节点有冲突
{ //直接返回false
return false;
}
}
events.Add(interval); //遍历完,时间没有冲突,事件也没有添加
return true; //说明这个事件在所有事件后面
}
定义区间的结构体
public struct Interval
{
public int x;
public int y;
public Interval(int x, int y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return string.Format("({0},{1})", x, y);
}
}
2.MyCalendar II
/*
* 升级版,同一时间可以添加两个事件,多于两个返回false
* MyCalendar.book(10, 20); // returns true
* MyCalendar.book(50, 60); // returns true
* MyCalendar.book(10, 40); // returns true
* MyCalendar.book(5, 15); // returns false
* MyCalendar.book(5, 10); // returns true
* MyCalendar.book(25, 55); // returns true
*
* 思路
* 1.用两个list保存事件,list1保存已经成功添加(包括没有区间重叠的喝有一次区间重叠的)的区间,list2保存有两层重叠的区间间隔
* 2.每次先在list2中查看是否有重叠区间,如果有直接返回false,若无则在list1中查看是否有重叠
* 3.若与list1有重叠,则把重叠部分的区间加入list2中,因为已经验证过与list2没有重叠所以直接添加list1并返回true
*/
List<Interval> list1 = new List<Interval>();
List<Interval> list2 = new List<Interval>();
private bool BookII(int start, int end)
{
Interval interval = new Interval(start, end);
foreach (var item in list2)
{
if (!(interval.x >= item.y || interval.y <= item.x))
return false;
}
for (int i = 0; i < list1.Count; i++)
{
if (interval.x >= list1[i].y || interval.y <= list1[i].x)
continue;
Interval temp = new Interval(Mathf.Max(interval.x, list1[i].x), Mathf.Min(interval.y, list1[i].y));
list2.Add(temp);
}
list1.Add(interval);
return true;
}
下面是一个巧妙的方法先看代码
Dictionary<int, int> map = new Dictionary<int, int>();
private bool BookII2(int start, int end)
{
if (map.ContainsKey(start))
map[start]++;
else
map.Add(start, 1);
if (map.ContainsKey(end))
map[end]--;
else
map.Add(end, -1);
//将时间节点按升序排序
map = map.OrderBy(o => o.Key).ToDictionary(k => k.Key, v => v.Value);
int count = 0;
foreach (var item in map)
{
count += item.Value;
if (count == 3)
{
//还原此次添加的值,返回false
map[start]--;
map[end]++;
return false;
}
}
return true;
}
* 思路:利用dictionary来存储各个时间节点出现次数(时间节点做Key,出现次数做Value),
* 如果是开始时间节点就把值+1,结束值节点就把值-1,然后遍历map,计算各个节点出现次数和,
* 如果次数和大于等于3(事实上等于的时候已经返回不可能大于)说明添加的事件重叠次数超过三次,返回false,并将 此次的start和end值还原
* 比如:当添加(10,20)时,将10,20添加到map
* 10 --> 1
* 20 --> -1 遍历时count最大为1<3 return true;
* 添加(50,60)时:
* 10 --> 1
* 20 --> -1
* 50 --> 1
* 60 --> -1 遍历时count最大为1<3 return true;
* 添加(10,40)时
* 10 --> 2
* 20 --> -1
* 40 --> -1
* 50 --> 1
* 60 --> -1 遍历时count最大为2<3 return true;
* 添加(5,15)时
* 5 --> 1
* 10 --> 2
* 15 --> -1
* 20 --> -1
* 40 --> -1
* 50 --> 1
* 60 --> -1 遍历时count最大为3 return false; 并将刚添加的值还原:5-->0,15-->0
* 添加(5,10)时
* 5 --> 1
* 10 --> 1
* 15 --> 0
* 20 --> -1
* 40 --> -1
* 50 --> 1
* 60 --> -1 遍历时count最大为2 return true;
*/
利用这个方法可以可以解决这个系列问题,不管时可以有一次时间区间重合,2次时间区间重合,还是n次时间区间重合,只需改变count 的判断值即可
区间有关题目: