leetcode problem:My Calendar1
Implement a
MyCalendar
class to store your events. A new event can be added if adding the event will not cause a double booking.Your class will have the method,
book(int start, int end)
. Formally, this represents a booking on the half open interval[start, end)
, the range of real numbersx
such thatstart <= x < end
.A double booking happens when two events have some non-empty intersection (ie., there is some time that is common to both events.)
For each call to the method
MyCalendar.book
, returntrue
if the event can be added to the calendar successfully without causing a double booking. Otherwise, returnfalse
and do not add the event to the calendar.Your class will be called like this:
MyCalendar cal = new MyCalendar();
MyCalendar.book(start, end)
Example 1:
MyCalendar(); MyCalendar.book(10, 20); // returns true MyCalendar.book(15, 25); // returns false MyCalendar.book(20, 30); // returns true Explanation: The first event can be booked. The second can't because time 15 is already booked by another event. The third event can be booked, as the first event takes every time less than 20, but not including 20.
Note:
- The number of calls to
MyCalendar.book
per test case will be at most1000
.- In calls to
MyCalendar.book(start, end)
,start
andend
are integers in the range[0, 10^9]
.
我们可以想象成这是一个“踢屁股”的问题,假设现在在坐标轴上有两个人(假设这A踢不到B的屁股),
然后你需要在这个坐标轴加入一个新的人,这里假设这个人加入在中间
我们现在就需要判断:C是否能踢到B的屁股 ;A是否能踢到C的屁股
明显可以看出,如果都踢不到,那就是证明C可以成功插入。
我们可以用 map[start] = end来表示,start表示人的位置,end表示腿长
class MyCalendar {
public:
map<int,int> books;
MyCalendar() {
}
bool book(int start, int end) {
auto it = books.lower_bound(start);
if(it!=books.end()&&end>it->first)return false; //C踢到B的屁股
if(it!=books.begin()&&(--it)->second > start)return false; //A踢到C的屁股
books[start]=end;
return true;
}
};
leetcode problem:My Calendar2
Implement a
MyCalendarTwo
class to store your events. A new event can be added if adding the event will not cause a triple booking.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 numbersx
such thatstart <= x < end
.A triple booking happens when three events have some non-empty intersection (ie., there is some time that is common to all 3 events.)
For each call to the method
Your class will be called like this:MyCalendar.book
, returntrue
if the event can be added to the calendar successfully without causing a triple booking. Otherwise, returnfalse
and do not add the event to the calendar.MyCalendar cal = new MyCalendar();
MyCalendar.book(start, end)
Example 1:
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 Explanation: The first two events can be booked. The third event can be double booked. The fourth event (5, 15) can't be booked, because it would result in a triple booking. The fifth event (5, 10) can be booked, as it does not use time 10 which is already double booked. The sixth event (25, 55) can be booked, as the time in [25, 40) will be double booked with the third event; the time [40, 50) will be single booked, and the time [50, 55) will be double booked with the second event.
Note:
- The number of calls to
MyCalendar.book
per test case will be at most1000
.- In calls to
MyCalendar.book(start, end)
,start
andend
are integers in the range[0, 10^9]
.
思路:
这题可以在My Calendar1的基础上改进,在My Calendar1上,我们不能让日期有交集(即不能踢到屁股),而在My Calendar2上,允许存在交集,但交集只允许是两个集合之间的,不能是多于两个集合之间的交集。
那么,我们可以专门把两个集合的交集记录下来,放在doubleBooking里面,在下次插入时间段到booking前,判断一下这个时间段是否与doubleBooking是否出现交集,即转化为在doubleBooking判断是否存在“踢屁股”。
如果没有出现“踢屁股”,那么我们就可以把当前这个时间段插入booking里面;
如果当前时间段与booking存在交集,则把这个交集插入doubleBooking里面。
class MyCalendarTwo {
public:
map<int,int> doubooks;
map<int,int> books;
bool book(int start, int end) {
auto next = doubooks.lower_bound(start);
if(next!=doubooks.end() && next->first<end)return false;
if(next!=doubooks.begin() && (--next)->second > start)return false;
for(auto p:books){
if(max(start,p.first) < min(end,p.second))
doubooks[max(start,p.first)] = min(end,p.second);
}
if(!books[start])books[start]=end;//需要判断代插入的时间段的start是否已经存在,如果存在的话,只需要把交集插入到doublebooking里面就行
return true;
}
};
注意:插入到booking前需要判断代插入的时间段的start是否已经存在,如果存在的话,会把之前的时间段覆盖掉哦。
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 numbersx
such thatstart <= 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
Your class will be called like this:MyCalendar.book
, return an integerK
representing the largest integer such that there exists aK
-booking in the calendar.MyCalendarThree cal = new MyCalendarThree();
MyCalendarThree.book(start, end)
Example 1:
MyCalendarThree(); MyCalendarThree.book(10, 20); // returns 1 MyCalendarThree.book(50, 60); // returns 1 MyCalendarThree.book(10, 40); // returns 2 MyCalendarThree.book(5, 15); // returns 3 MyCalendarThree.book(5, 10); // returns 3 MyCalendarThree.book(25, 55); // returns 3 Explanation: The first two events can be booked and are disjoint, so the maximum K-booking is a 1-booking. The third event [10, 40) intersects the first event, and the maximum K-booking is a 2-booking. The remaining events cause the maximum K-booking to be only a 3-booking. Note that the last event locally causes a 2-booking, but the answer is still 3 because eg. [10, 20), [10, 40), and [5, 15) are still triple booked.
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]
.
思路:
我们可以用“推车子装货”的思想去求出最大K
我们可以把start 标记为1(装货) ;把end标记为 -1(卸货)
我们可以从左到右进行遍历,把数值一个一个加起来,记录最大值(装进货物最多的时候)。这个最大值就是我们的K。
class MyCalendarThree {
public:
map<int ,int> timeline;
MyCalendarThree() {
}
int book(int start, int end) {
timeline[start]++;
timeline[end]--;
int maxK=0,ongoing=0;
for(pair<int,int> t:timeline){
maxK = max(maxK,ongoing+=t.second);
}
return maxK;
}
};