Problem
Implement a MyCalendarThree
class to store your events. A new event can always be added.
Your class will have one method, book(int start, int end)
. Formally, this represents a booking on the half open interval [start, end)
, the range of real numbers x
such that start <= x < end
.
A K-booking happens when K events have some non-empty intersection (ie., there is some time that is common to all K events.)
For each call to the method MyCalendar.book
, return an integer K
representing the largest integer such that there exists a K
-booking in the calendar.
Your class will be called like this: MyCalendarThree cal = new MyCalendarThree()
; MyCalendarThree.book(start, end)
Example1:
1 | MyCalendarThree(); |
Note:
- The number of calls to
MyCalendarThree.book
per test case will be at most400
. - In calls to
MyCalendarThree.book(start, end)
,start
andend
are integers in the range[0, 10^9]
.
Analysis
本题是Calendar系列的第三题,难度比起前两题有了提升,但是本质上是一样的。我在Calendar Ⅱ中提到了一个多级的集合,这道题的任务就是统计多级集合的级数。但是由于区间重叠的次数是未知的,而且,大量创建vector的会使得代码的效率降低,因此我寻求是否有另一种更加高效简便的方法。
答案当然是有的。我们先来考虑一个情景:一个人参加多个视频会议,每次进入会议室之前他必须先输入账号和密码(登陆),每次结束会议后需要输入账号和密码(登出),那么在任意时刻中,我们只需要统计当前账户登陆的次数就可以知道,该人同时在参加多少个会议。
回到这道题,对于整一个时间轴,我们使用一个map来存储,key是事件的start
或end
,value是该时间点在线的次数。于是,我们就得到了一条时间轴,我们只需要找出在时间轴上最大的在线数量,即是答案了。
Solution
使用map来存储一条时间轴,原因是map具有对key自动排序的功能。对于每一个需要判断的区间,我们首先在时间轴上进行登录(+1)和登出(-1)操作。然后我们遍历这个map,使用一个cursor
加上每个时间点对应的value,找出其中最大的在线次数即可。
Code
1 | class MyCalendarThree { |
运行时间:88ms,超过40.97%的CPP代码。
Summary
Calendar系列的三道题是难度递增的,他们的思路也是一致的。难点还是在第三题中,如何把问题抽象出一个开会的模式,只要理解了这个模式,实现起来就方便很多了。本题的分析就到这里,谢谢!