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 numbers x such that start <= x < end.

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 MyCalendar.book, return true if the event can be added to the calendar successfully without causing a triple booking. Otherwise, return false 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(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 most 1000.
  • In calls to MyCalendar.book(start, end)start and end are integers in the range [0, 10^9].

这道题是 My Calendar I 的拓展,之前那道题说是不能有任何的重叠区间,而这道题说最多容忍两个重叠区域,注意是重叠区域,不是事件。比如事件 A,B,C 互不重叠,但是有一个事件D,和这三个事件都重叠,这样是可以的,因为重叠的区域最多只有两个。所以关键还是要知道具体的重叠区域,如果两个事件重叠,那么重叠区域就是它们的交集,求交集的方法是两个区间的起始时间中的较大值,到结束时间中的较小值。可以用一个 TreeSet 来专门存重叠区间,再用一个 TreeSet 来存完整的区间,那么思路就是,先遍历专门存重叠区间的 TreeSet,因为能在这里出现的区间,都已经是出现两次了,如果当前新的区间跟重叠区间有交集的话,说明此时三个事件重叠了,直接返回 false。如果当前区间跟重叠区间没有交集的话,则再来遍历完整区间的集合,如果有交集的话,那么应该算出重叠区间并且加入放重叠区间的 TreeSet 中。最后记得将新区间加入完整区间的 TreeSet 中,参见代码如下:

解法一:

class MyCalendarTwo {
public:
MyCalendarTwo() {} bool book(int start, int end) {
for (auto &a : s2) {
if (start >= a.second || end <= a.first) continue;
return false;
}
for (auto &a : s1) {
if (start >= a.second || end <= a.first) continue;
s2.insert({max(start, a.first), min(end, a.second)});
}
s1.insert({start, end});
return true;
} private:
set<pair<int, int>> s1, s2;
};

下面这种方法相当的巧妙,建立一个时间点和次数之间的映射,规定遇到起始时间点,次数加1,遇到结束时间点,次数减1。那么首先更改新的起始时间 start 和结束时间 end 的映射,start 对应值增1,end 对应值减1。然后定义一个变量 cnt,来统计当前的次数。使用 TreeMap 具有自动排序的功能,所以遍历的时候就是按时间顺序的,最先遍历到的一定是一个起始时间,所以加上其映射值,一定是个正数。如果此时只有一个区间,就是刚加进来的区间的话,那么首先肯定遍历到 start,那么 cnt 此时加1,然后就会遍历到 end,那么此时 cnt 减1,最后下来 cnt 为0,没有重叠。还是用具体数字来说吧,现在假设 TreeMap 中已经加入了一个区间 [3, 5) 了,就有下面的映射:

3 -> 1

5 -> -1

假如此时要加入的区间为 [3, 8) 的话,则先对3和8分别加1减1,此时的映射为:

3 -> 2

5 -> -1

8 -> -1

最先遍历到3,cnt 为2,没有超过3,此时有两个事件有重叠,是允许的。然后遍历5和8,分别减去1,最终又变成0了,始终 cnt 没有超过2,所以是符合题意的。如果此时再加入一个新的区间 [1, 4),则先对1和4分别加1减1,那么此时的映射为:

1 -> 1

3 -> 2

4 -> -1

5 -> -1

8 -> -1

先遍历到1,cnt为1,然后遍历到3,此时 cnt 为3了,那么就知道有三个事件有重叠区间了,所以这个新区间是不能加入的,需要还原其 start 和 end 做的操作,把 start 的映射值减1,end 的映射值加1,然后返回 false。否则没有三个事件有共同重叠区间的话,返回 true 即可,参见代码如下:

解法二:

class MyCalendarTwo {
public:
MyCalendarTwo() {} bool book(int start, int end) {
++freq[start];
--freq[end];
int cnt = ;
for (auto f : freq) {
cnt += f.second;
if (cnt == ) {
--freq[start];
++freq[end];
return false;
}
}
return true;
} private:
map<int, int> freq;
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/731

类似题目:

My Calendar I

参考资料:

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

https://leetcode.com/problems/my-calendar-ii/discuss/109550/Simple-AC-by-TreeMap

https://leetcode.com/problems/my-calendar-ii/discuss/109522/Simplified-winner's-solution

https://leetcode.com/problems/my-calendar-ii/discuss/109519/JavaC%2B%2B-Clean-Code-with-Explanation

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 731. My Calendar II 我的日历之二的更多相关文章

  1. [LeetCode] My Calendar II 我的日历之二

    Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...

  2. LeetCode 731. My Calendar II

    原题链接在这里:https://leetcode.com/problems/my-calendar-ii/ 题目: Implement a MyCalendarTwo class to store y ...

  3. 【LeetCode】731. My Calendar II 解题报告(Python)

    [LeetCode]731. My Calendar II 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题 ...

  4. [LeetCode] 729. My Calendar I 731. My Calendar II 732. My Calendar III 题解

    题目描述 MyCalendar主要实现一个功能就是插入指定起始结束时间的事件,对于重合的次数有要求. MyCalendar I要求任意两个事件不能有重叠的部分,如果插入这个事件会导致重合,则插入失败, ...

  5. 731. My Calendar II

    Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...

  6. [LeetCode] Number of Islands II 岛屿的数量之二

    A 2d grid map of m rows and n columns is initially filled with water. We may perform an addLand oper ...

  7. [LeetCode] 685. Redundant Connection II 冗余的连接之二

    In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...

  8. [LeetCode] Shortest Word Distance II 最短单词距离之二

    This is a follow up of Shortest Word Distance. The only difference is now you are given the list of ...

  9. [LeetCode] Pascal's Triangle II 杨辉三角之二

    Given an index k, return the kth row of the Pascal's triangle. For example, given k = 3,Return [1,3, ...

随机推荐

  1. ubuntu16.04 下anaconda3安装教程

    贴一个成功的连接: https://blog.csdn.net/u012243626/article/details/82469174

  2. Delta-wave HDU - 1030

    Delta-wave HDU - 1030 A triangle field is numbered with successive integers in the way shown on the ...

  3. 什么是JavaBean?

    什么是JavaBean? 首先明确的是JavaBean是一种Java类,而且是一种特殊的.可重用的类. 必须具有无参数的构造器,所有的属性都是private的,通过提供setter和getter方法来 ...

  4. docker命令之link

    1.新建两台容器,第二台(busybox_2)link到第一台(busybox_1) [root@localhost ~]# docker run -d -it --name busybox_1 bu ...

  5. 排障利器之远程调试与监控 --jmx & remote debug

    监控和调试功能是应用必备的属性之一,其手段也是多种多样. 一般地,我们可以通过:线上日志, zabbix, grafana, cat 等待系统做一问题留底,有问题及时报警,从而达到监控效果. 而对于应 ...

  6. Kafka学习笔记之Kafka性能测试方法及Benchmark报告

    0x00 概述 本文主要介绍了如何利用Kafka自带的性能测试脚本及Kafka Manager测试Kafka的性能,以及如何使用Kafka Manager监控Kafka的工作状态,最后给出了Kafka ...

  7. EF CodeFirst 使用T4模板

    实用等级:★★★★★ 首先,定义一个接口,代表一个领域实体.在定义一个实体集成这个接口,面向接口编程的各种好处就不提了. /// <summary> /// 代表一个领域实体 /// &l ...

  8. LinuxShell——特殊符号

    LinuxShell——特殊符号 摘要:本文主要学习了Shell命令中具有特殊功能的一些符号. 多命令执行 顺序执行“;” 如果使用“;”连接多条命令,那么这些命令会依次执行,但是各命令之间没有任何逻 ...

  9. matlab 基础语法

    计算次幂 Trial>> 3 ^ 2 % 3 raised to the power of 2 ans = 9 MATLAB 计算正弦值 Trial>> sin(pi /2) ...

  10. wpf 打开win8系统软件盘

    三个函数 一) /// <summary> /// 判断进程是否正在运行 /// </summary> /// <param name="process&quo ...