Skip to content
本页目录

0731-我的日程安排表II

题目描述

https://leetcode.cn/problems/my-calendar-ii

实现一个 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(); 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 解释: 前两个日程安排可以添加至日历中。 第三个日程安排会导致双重预订,但可以添加至日历中。 第四个日程安排活动(5,15)不能添加至日历中,因为它会导致三重预订。 第五个日程安排(5,10)可以添加至日历中,因为它未使用已经双重预订的时间10。 第六个日程安排(25,55)可以添加至日历中,因为时间 [25,40] 将和第三个日程安排双重预订; 时间 [40,50] 将单独预订,时间 [50,55)将和第二个日程安排双重预订。

提示:

每个测试用例,调用 MyCalendar.book 函数最多不超过 1000次。 调用函数 MyCalendar.book(start, end)时, start 和 end 的取值范围为 [0, 10^9]。

思路

因为不能有重叠两次,所以最多重叠一次,当我们发现新加入的区间就在重叠区域时,就返回false。 注意有两个地方

  1. 关于重叠区域,如果每次添加添加数据的时候才计算重叠区域,则要把原来的数据重新遍历一遍,时间复杂度很高,可以单独开辟一个数组储存重叠区域,这样新加入区间时只比较重叠区域就可以了

  2. 关于重叠区域的判断, [s1,e1) 和 [s2,e2) 如果 s1 < e2 且 s2 < e1 则会出现重叠 ,这个条件其实是 s1 >= e2 或者 s2 >=e1 的反条件。 当一个区域的起点,在另一个区域终点后面的时候,他们必然是没有重叠的,反条件则是有重叠

csharp
public class MyCalendarTwo {

    private List<IList<int>> booked;
    private List<IList<int>> overlaps;

    public MyCalendarTwo() {
        booked = new List<IList<int>>();
        //把重叠的区域加进去,这样只需要判断是否在重叠区域里面
        overlaps = new List<IList<int>>();
    }
    
    public bool Book(int start, int end) {
        //对于区域 [s1,e1) 和 [s2,e2) 如果 s1 < e2 或者 s2 < e1 则会出现重叠
        for(int i=0; i<overlaps.Count; i++){
            int left = overlaps[i][0]; 
            int right = overlaps[i][1]; 
            if(start < right && left < end){
                return false;
            }
        }
        //加入区域,注意也加入重叠的区域 
        for(int i = 0; i<booked.Count; i++){
            int left = booked[i][0];
            int right = booked[i][1];
            //这里注意:求 left-->right 和 start-->end的交集
            //如果 left >= end 或者 start >= right 就没有交集了,所以条件如下
            if(left < end && start < right){
                overlaps.Add(new List<int>{ Math.Max(start,left), Math.Min(end,right) });
            }
        }
        booked.Add(new List<int>{start,end});
        return true;
    }
}

快速复习

csharp
public class MyCalendarTwo {

    private List<IList<int>> booked, overlaps;

    public MyCalendarTwo() {
        booked = new List<IList<int>>();
        overlaps = new List<IList<int>>();
    }
    
    public bool Book(int start, int end) {
        int start2 = start, end2 = end;
        for(int i=0; i<overlaps.Count; i++){
            int start1 = overlaps[i][0];
            int end1 = overlaps[i][1];
            if(start1 < end2 && start2 < end1){
                return false;
            }
        }
        for(int i=0; i<booked.Count; i++){
            int start1 = booked[i][0];
            int end1 = booked[i][1];
            if(start1 < end2 && start2 < end1){
                overlaps.Add(new List<int>{ Math.Max(start1,start2),Math.Min(end1,end2)  });
            }
        }
        booked.Add(new List<int>{start,end});
        return true;
    }
}

Released under the MIT License.