一刷243-剑指 Offer II 058. 日程表(同:729. 我的日程安排表 I)

题目:
请实现一个 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.EntryMap的一个内部接口
此接口为泛型,定义为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);
   获取在当前时间段后的最接近的时间

  */

LC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值