题目:
请实现一个 MyCalendar 类来存放你的日程安排。
如果要添加的时间内没有其他安排,则可以存储这个新的日程安排。
MyCalendar 有一个 book(int start, int end)方法。
它意味着在 start 到 end 时间内增加一个日程安排,
注意,这里的时间是半开区间,即 [start, end), 实数 x 的范围为, start <= x < end。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生重复预订。
每次调用 MyCalendar.book方法时,如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true
否则,返回 false 并且不要将该日程安排添加到日历中。
请按照以下步骤调用 MyCalendar 类:
MyCalendar cal = new MyCalendar();
MyCalendar.book(start, end)
---------------------------
示例:
输入:
["MyCalendar","book","book","book"]
[[],[10,20],[15,25],[20,30]]
输出: [null,true,false,true]
解释:
MyCalendar myCalendar = new MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false ,第二个日程安排不能添加到日历中,因为时间 15 已经被第一个日程安排预定了
MyCalendar.book(20, 30); // returns true ,第三个日程安排可以添加到日历中,因为第一个日程安排并不包含时间 20
提示:
每个测试用例,调用 MyCalendar.book 函数最多不超过 1000次。
0 <= start < end <= 109
--------------------------
思路:
本题的难点主要是容器的选择,这个先不说,我们先说说解题思路:
假设我们有一个容器,用来保存时间段<start,end>。
每当要预定一个时间段<start,end>的时候,先到容器中查找两段时间。
floorPeriod: 比当前预定时间段前的最近一段时间。
ceilPeriod:比当前预定时间段后的最近一段时间。
如果 floorPeriod 的结束时间 <= start && end <= ceilPeriod 的开始时间,则可以预定,否则不能预定。
此题的思路是不是很简单呀,这道题难的其实是下面这个容器的选择,容器需要具备以下的功能:
存储 <start, end> 时间段。
能够快速地在容器中找到比 特定时间 小或者大的时间段。
满足以上要求的容器就是红黑树,Java 中的 TreeMap 就是红黑树实现的 。
------------
Map是java中的接口,Map.Entry是Map的一个内部接口
此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)
floorEntry(K key) 方法用来返回与最大键小于或等于给定的键,
或者如果不存在这样的键,null关联的键 - 值映射。
ceilingEntry(K key) 方法用来返回与该键至少大于或等于给定键,
如果不存在这样的键的键 - 值映射,则返回null相关联。
(1) Object getKey(): 返回条目的关键字
(2) Object getValue(): 返回条目的值
-----------------------
class MyCalendar {
private TreeMap<Integer, Integer> timeMap;//用红黑树存储[start, end]段,根据时间start排序
public MyCalendar() {//初始化
timeMap = new TreeMap<>();
}
public boolean book(int start, int end) {
Map.Entry<Integer, Integer> floorPeriod = timeMap.floorEntry(start);
Map.Entry<Integer,Integer> ceilingPeriod = timeMap.ceilingEntry(start);
int lastEnd = Integer.MIN_VALUE;//记录在 当前时间段前的最近时间的 结束时间
int nextStart = Integer.MAX_VALUE;//记录在 当前时间段后的最近时间的 开始时间
if (floorPeriod != null) {
lastEnd = floorPeriod.getValue();//getValue 得到上一个时间段的结束时间
}
if (ceilingPeriod != null) {
nextStart = ceilingPeriod.getKey();//getKey 得到下一个时间段的开始时间
}
if (lastEnd <= start && end <= nextStart) {//当前时间段 在 前后两个时间段之间
timeMap.put(start, end);
return true;
}
return false;
}
}
/**
* Your MyCalendar object will be instantiated and called as such:
* MyCalendar obj = new MyCalendar();
* boolean param_1 = obj.book(start,end);
*/
/**
Map.Entry<Integer, Integer> floorPeriod = timeMap.floorEntry(start);
获取在当前时间段之前的最接近的时间
Map.Entry<Integer,Integer> ceilPeriod = timeMap.ceilingEntry(start);
获取在当前时间段后的最接近的时间
*/
一刷243-剑指 Offer II 058. 日程表(同:729. 我的日程安排表 I)
最新推荐文章于 2024-09-14 18:52:56 发布