1. 问题描述:
实现一个 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)
示例 1:
MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false
MyCalendar.book(20, 30); // returns true
解释:
第一个日程安排可以添加到日历中. 第二个日程安排不能添加到日历中,因为时间 15 已经被第一个日程安排预定了。第三个日程安排可以添加到日历中,因为第一个日程安排并不包含时间 20 。
说明:
每个测试用例,调用 MyCalendar.book 函数最多不超过 1000次。
调用函数 MyCalendar.book(start, end)时, start 和 end 的取值范围为 [0, 10 ^ 9]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/my-calendar-i
2. 思路分析:
分析题目可以知道这道题目类似于力扣的715题,这道题目是715题的简化版,因为使用的是python语言所以对于插入区间的操作我们可以使用bisect模块的insort_left方法来插入一个区间到S中(python可以使用列表来维护区间),这样可以使得插入当前的区间之后还可以维护一个有序的序列(c++可以使用pair来维护一个区间,将pair插入到set中这样可以维护一个有序序列),这样插入操作解决了,所以这道题目的关键是如何判断当前区间与之前插入的区间是否存在交集,类似715题我们可以使用二分查找出大于等于start的第一个区间t,以这个位置作为分界线,判断区间t与t的上一个区间t - 1是否与当前的区间存在交集,如果其中一个存在交集返回False,如果这两个区间与当前的区间都没有交集说明其余的区间与当前的区间也是没有交集的,将当前区间插入到S中并且返回True即可(判断左右两边的第一个区间)。
3. 代码如下:
import bisect
# 使用bisect使得插入整个区间是有序的, 这样就可以使用二分查找了
class MyCalendar:
def __init__(self):
S = list()
self.S = S
INF = 2 * 10 ** 9
# 加入两个边界方便处理, 这样后面在查找区间的时候就不用判断边界情况
S.append([-INF, -INF])
S.append([INF, INF])
# 在S中二分查找第一个大于等于x的位置
def binarySearch(self, x: int):
S = self.S
l, r = 0, len(S)
while l < r:
mid = l + r >> 1
if S[mid][0] >= x:
r = mid
else:
l = mid + 1
return r
def book(self, start: int, end: int) -> bool:
S = self.S
t = self.binarySearch(start)
k = t - 1
# 判断左右两个区间是否与当前的区间有交集
if S[t][0] < end: return False
if k >= 0 and S[k][1] > start: return False
bisect.insort_left(S, [start, end])
return True