[LeetCode] My Calendar II 我的日历之二
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.
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 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.bookper test case will be at most1000. - In calls to
MyCalendar.book(start, end),startandendare 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
类似题目:
参考资料:
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] My Calendar II 我的日历之二的更多相关文章
- [LeetCode] 731. My Calendar II 我的日历之二
Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...
- [LeetCode] My Calendar III 我的日历之三
Implement a MyCalendarThree class to store your events. A new event can always be added. Your class ...
- [LeetCode] My Calendar I 我的日历之一
Implement a MyCalendar class to store your events. A new event can be added if adding the event will ...
- [LeetCode] Palindrome Permutation II 回文全排列之二
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empt ...
- [LeetCode] Redundant Connection II 冗余的连接之二
In this problem, a rooted tree is a directed graph such that, there is exactly one node (the root) f ...
- [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列
A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...
- [LeetCode] Contains Duplicate II 包含重复值之二
Given an array of integers and an integer k, return true if and only if there are two distinct indic ...
- [LeetCode] Single Number II 单独的数字之二
Given an array of integers, every element appears three times except for one. Find that single one. ...
- [LeetCode] Path Sum II 二叉树路径之和之二
Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...
随机推荐
- Java基础学习笔记二十六 JDBC
什么是JDBC JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.原来我们操作数据库是在控制台使用SQL语句来操作数据库,J ...
- 用jQuery.delegate()将事件绑定在父元素上面
1.先看看官方的示例: <html> <head> <script type="text/javascript" src="/jquery/ ...
- 20162311 实验三 敏捷开发与XP实践 实验报告
20162311 实验三 敏捷开发与XP实践 实验报告 实验内容 一.研究学习IDEA中的Code菜单 使用Code ->Reformate Code功能将以下代码格式化 public clas ...
- Alpha冲刺Day8
Alpha冲刺Day8 一:站立式会议 今日安排: 经过为期5天的冲刺,基本完成企业人员模块的开发.因第三方机构与企业存在委托的关系.第三方人员对于风险的自查.风险列表的展示以及自查风险的统计展示(包 ...
- Linux挂载
1 文件系统中相关目录 dev:设备文件 media:挂载媒体设备,如光驱,U盘 mnt:让用户临时挂载别的文件系统 2 磁盘分区相关知识 1)磁盘包括IDE和SCSI两种接口: IDE接口:速度慢但 ...
- NetFPGA-1G-CML Demo --- openflow_switch
环境 ubuntu 14.04 vivado 15.2 ise 14.6 更多基础配置:http://www.cnblogs.com/wpqwpq/p/6771568.html 运行步骤 step1: ...
- python 进程复习
import os import time ret = os.fork() # 创建子线程 if ret ==0: # 子进程中返回值为0,父进程>0 while True: print('.. ...
- Flask jinja2 全局函数,宏
内置全局函数 dict()函数,方便生成字典型变量 {% set user = dict(name='Mike',age=15) %} <p>{{ user | tojson | safe ...
- Autowired注解
package com.how2java.pojo; import org.springframework.beans.factory.annotation.Autowired; public cla ...
- CISCO路由器练习
前言: 总结了昨天的学习和今天的单臂路由 写了今天的文章. 目录: 路由器的基本配置 单臂路由的练习 正文: 路由器基本配置 环境要求 cisco模拟器 2台交换机 2台PC 1台路由器 路由器介绍: ...