Medium
题目描述
实现一个 MyCalendar 类来存放你的日程安排。如果要添加的日程安排不会造成 重复预订 ,则可以存储这个新的日程安排。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生 重复预订。
日程可以用一对整数 startTime 和 endTime 表示,这里的时间是半开区间,即 [startTime, endTime), 实数 x 的范围为,startTime <= x < endTime。
实现 MyCalendar 类:
MyCalendar()初始化日历对象。boolean book(int startTime, int endTime)如果可以将日程安排成功添加到日历中而不会导致重复预订,返回true。否则,返回false并且不要将该日程安排添加到日历中。
示例:
输入:
["MyCalendar", "book", "book", "book"]
[[], [10, 20], [15, 25], [20, 30]]
输出:
[null, true, false, true]
解释:
MyCalendar myCalendar = new MyCalendar();
myCalendar.book(10, 20); // return True
myCalendar.book(15, 25); // return False ,这个日程安排不能添加到日历中,因为时间 15 已经被另一个日程安排预订了。
myCalendar.book(20, 30); // return True ,这个日程安排可以添加到日历中,因为第一个日程安排预订的每个时间都小于 20 ,且不包含时间 20 。
提示:
0 <= start < end <= 10^9- 每个测试用例,调用
book方法的次数最多不超过1000次。
解题思路
解题思路
这道题要求实现一个日程安排系统,核心是判断新的时间段是否与已存在的时间段冲突。
方法一:暴力法(推荐)
最直观的方法是维护一个已预订时间段的列表,每次添加新预订时,遍历所有已存在的时间段,检查是否有冲突。
冲突判断:两个时间段 [a, b) 和 [c, d) 冲突的条件是:max(a, c) < min(b, d),等价于 a < d && c < b。
方法二:有序集合 + 二分查找
将预订按起始时间排序,使用二分查找定位新预订的插入位置,只需检查相邻的时间段。这种方法在预订数量很大时更高效。
方法三:平衡二叉搜索树
使用 TreeMap 或 set 等数据结构维护有序的时间段,查找和插入的时间复杂度都是 O(log n)。
考虑到题目约束(最多1000次调用),暴力法已经足够高效且实现简单,因此推荐使用方法一。
代码实现
class MyCalendar {
private:
vector<pair<int, int>> bookings;
public:
MyCalendar() {
}
bool book(int startTime, int endTime) {
for (auto& booking : bookings) {
if (startTime < booking.second && endTime > booking.first) {
return false;
}
}
bookings.push_back({startTime, endTime});
return true;
}
};
class MyCalendar:
def __init__(self):
self.bookings = []
def book(self, startTime: int, endTime: int) -> bool:
for start, end in self.bookings:
if startTime < end and endTime > start:
return False
self.bookings.append((startTime, endTime))
return True
public class MyCalendar {
private List<(int start, int end)> bookings;
public MyCalendar() {
bookings = new List<(int, int)>();
}
public bool Book(int startTime, int endTime) {
foreach (var booking in bookings) {
if (startTime < booking.end && endTime > booking.start) {
return false;
}
}
bookings.Add((startTime, endTime));
return true;
}
}
var MyCalendar = function() {
this.bookings = [];
};
MyCalendar.prototype.book = function(startTime, endTime) {
for (let booking of this.bookings) {
if (startTime < booking[1] && endTime > booking[0]) {
return false;
}
}
this.bookings.push([startTime, endTime]);
return true;
};
复杂度分析
| 方法 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 暴力法 | O(n) per book, O(n²) total | O(n) |
| 二分查找 | O(n log n) per book | O(n) |
其中 n 是已预订的时间段数量。对于题目给定的约束(最多1000次调用),暴力法的性能完全满足要求。
相关题目
. My Calendar II (Medium)
. My Calendar III (Hard)