[LeetCode] 729. My Calendar I 731. My Calendar II 732. My Calendar III 题解
题目描述
MyCalendar主要实现一个功能就是插入指定起始结束时间的事件,对于重合的次数有要求。
- MyCalendar I要求任意两个事件不能有重叠的部分,如果插入这个事件会导致重合,则插入失败,不进行插入;否则插入并返回true。
- My Calendar II要求任意三个事件不能有重叠的部分,但是两个事件可以有重叠。同样是成功返回true,失败返回false。
- My Calendar III没有要求,对于每次插入新事件,求当前总体最大的重叠事件的个数。
MyCalendar I
对于不能重合的事件,可以利用BST二叉搜索树,每个节点代表一个事件区间,如果要插入的部分全部在当前节点的左侧或者右侧,则左递归或者右递归,否则,插入失败。
如果是用循环实现,则需要保存插入节点的父节点以及是父节点的左子还是右子。循环实现的代码如下:
class Node {//节点有起始结束时间和左右子节点
public Node(int start, int end) {
l = start;
r = end;
}
int l, r;
Node left, right;
}
Node root = null;
public boolean book(int start, int end) {
if (root == null) {
root = new Node(start, end);
} else {
Node cur = root;
Node pre = null;//父节点
boolean leftTag = false;//记录该插入的节点是左子还是右子
while (cur != null) {
pre = cur;
if (end <= cur.l) {//应该在当前节点的左侧,往左子递归
leftTag = true;
cur = cur.left;
} else if (start >= cur.r) {//应该在当前节点的右侧,往右子递归
leftTag = false;
cur = cur.right;
} else {// 有重叠,不应该插入,返回false
return false;
}
}
if (leftTag) {//根据tag确定是父亲的左子还是右子
pre.left = new Node(start, end);
} else {
pre.right = new Node(start, end);
}
}
return true;
}
My Calendar II
用TreeMap保存所有事件开始及终止的位置以及它们的次数,<start,次数(正)>,和<end,次数(负数)>。要插入这个事件的实现过程是:先插入这个事件,再检测这个事件如果会导致>2个的区间有重合,则又取消插入,返回false,否则返回true。检测的方法是:遍历treemap中的entry(TreeMap是有序的),cnt+=entry.getValue()记录当前时刻开始了还没结束的事件个数。
TreeMap<Integer,Integer> treeMap;
public MyCalendarTwo() {
treeMap=new TreeMap<>();
}
public boolean book(int start, int end) {
int a=treeMap.getOrDefault(start,0);
int b=treeMap.getOrDefault(end,0);
treeMap.put(start,a+1);
treeMap.put(end,b-1);
int count=0;
for (Integer val : treeMap.values()) {
count+=val;//记录当前已开始但未结束的事件个数
if(count>2){//如果事件个数>2,则说明有三个或者以上的重叠,不满足条件,要取消刚刚的插入
if(a==0){//如果插入前的个数为0则可以直接删除这条记录,否则对次数进行更改
treeMap.remove(start);
}else{
treeMap.put(start,a);
}
if(b==0){
treeMap.remove(end);
}else{
treeMap.put(end,b);
}
return false;
}
}
return true;
}
My Calendar III
和第一题一样使用BST,没有重叠的区间的节点操作类似第一题,但是对于有重叠区间的节点,要进行分裂,把lser,lsre,slre,sler四种情况总结起来就是中间两个值作为当前节点的起始和终止时间,且次数要增加,两侧分别进行左递归和右递归,次数根据lr还是se再外侧来决定。【selr分别为待插入的start,end,当前节点的left和right】
注意,次数不能简单的为1,对于分裂了lr的情况(如lser和lsre、sler),递归的时候次数可能要指定为当前节点的已有次数,而这个不是固定为1的。所以插入次数也要作为参数进行传递。
class Node {//节点有起始终止事件,左右子节点,这个时间区间的重叠次数
int left, right;
int count;
Node leftChild, rightChild;
public Node(int l, int r, int c) {
left = l;
right = r;
count = c;
}
}
int maxK = 1;//只要调用1次book,则最大记录至少为1,所以可以直接初始化为1
Node root;
public int book(int start, int end) {
root = insert(root, start, end, 1);
return maxK;
}
private Node insert(Node root2, int start, int end, int c) {//由于需要修改节点的链接关系,所以需要返回节点
if (start >= end) {// no need to take action
return root2;
}
if (root2 == null) {
root2 = new Node(start, end, c);
return root2;
}
int l = root2.left;
int r = root2.right;
if (end <= l) {//一定落在当前节点的左侧即左子树上,进行左递归
root2.leftChild = insert(root2.leftChild, start, end, c);
} else if (start >= r) {
root2.rightChild = insert(root2.rightChild, start, end, c);
} else {
int[] a = new int[4];//给四个值排序
if (start <= l) {
a[0] = start;
a[1] = l;
} else {
a[0] = l;
a[1] = start;
}
if (end <= r) {
a[2] = end;
a[3] = r;
} else {
a[2] = r;
a[3] = end;
}
root2.left = a[1];//中间的两个值作为当前节点的值
root2.right = a[2];
root2.leftChild = insert(root2.leftChild, a[0], a[1], start <= l ? c : root2.count);//左递归,如果start在外侧,则次数为c;如果l在外侧,则次数为当前节点的次数
root2.rightChild = insert(root2.rightChild, a[2], a[3], end >= r ? c : root2.count);
root2.count += c;//当前节点的次数要增加,并且根据大小情况选择性的更新maxK
maxK = Math.max(maxK, root2.count);
}
return root2;
}
[LeetCode] 729. My Calendar I 731. My Calendar II 732. My Calendar III 题解的更多相关文章
- 【LeetCode】732. My Calendar III解题报告
[LeetCode]732. My Calendar III解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/my-calendar ...
- Leetcode 137. 只出现一次的数字 II - 题解
Leetcode 137. 只出现一次的数字 II - 题解 137. Single Number II 在线提交: https://leetcode.com/problems/single-numb ...
- C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...
- [Leetcode 90]求含有重复数的子集 Subset II
[题目] Given a collection of integers that might contain duplicates, nums, return all possible subsets ...
- Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted)
Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted) 给定一个已按照升序排列 的有序数组,找到两个数使得它们 ...
- Leetcode之回溯法专题-212. 单词搜索 II(Word Search II)
Leetcode之回溯法专题-212. 单词搜索 II(Word Search II) 给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词. 单 ...
- Leetcode之回溯法专题-52. N皇后 II(N-Queens II)
Leetcode之回溯法专题-52. N皇后 II(N-Queens II) 与51题的代码80%一样,只不过52要求解的数量,51求具体解,点击进入51 class Solution { int a ...
- Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II)
Leetcode之回溯法专题-40. 组合总和 II(Combination Sum II) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使 ...
- Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III)
Leetcode之动态规划(DP)专题-123. 买卖股票的最佳时机 III(Best Time to Buy and Sell Stock III) 股票问题: 121. 买卖股票的最佳时机 122 ...
随机推荐
- 在 vscode.dev 中直接运行 Python !纯浏览器环境,无后端!
其实有挺长一段时间没有写自己的 VS Code 插件了! 还是要感谢我们 DevDiv 组的 Flexible Friday 活动,让我可以在工作日研究自己感兴趣的项目. Flexible Frida ...
- springcloud - alibaba快速上手 - 更新完毕
1.简单对比一下springcloud与springcloud-alibaba 2.准备知识 官网:https://nacos.io/zh-cn/ 查看cloud和springboot的对应关系 ht ...
- abandon, abbreviation
abandon 近/反义词: continue, depart, desert (做动词时读作diˈzəːt), discard, give up, quit, surrender搭配: altoge ...
- day6 基本数据类型及内置方法
day6 基本数据类型及内置方法 一.10进制转其他进制 1. 十进制转二进制 print(bin(11)) #0b1011 2. 十进制转八进制 print(hex(11)) #0o13 3. 十进 ...
- Hive(一)【基本概念、安装】
目录 一. Hive基本概念 1.1 Hive是什么 1.2 Hive的优缺点 1.3 Hive的架构 1.4 Hive和数据库的区别 二. Hive安装 2.1 安装地址 2.2 Mysql的安装 ...
- 爬虫系列:使用 MySQL 存储数据
上一篇文章我们讲解了爬虫如何存储 CSV 文件,这篇文章,我们讲解如何将采集到的数据保存到 MySQL 数据库中. MySQL 是目前最受欢迎的开源关系型数据库管理系统.一个开源项目具有如此之竞争力实 ...
- 2019广东工业大学新生杯决赛 I-迷途的怪物
题目:I-I-迷途的怪物_2019年广东工业大学腾讯杯新生程序设计竞赛(同步赛) (nowcoder.com) 将(p-1)^n 按照多项式定理拆开,会发现只有一项没有p,其余项都有p,可直接约掉. ...
- 100个Shell脚本——【脚本9】统计ip
[脚本9]统计ip 有一个日志文件,日志片段:如下: 112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com "/ ...
- Oracle存储过程游标for循环怎么写
一.不带参数的游标for循环 首先编写存储过程的整体结构,如下: create or replace procedure test_proc is v_date date; --变量定义 begin ...
- 【Linux】【Basis】CentOS启动流程
1. 基础概念 1.1 Linux系统的组成部分:内核+根文件系统 内核:进程管理.内存管理.网络协议栈.文件系统.驱动程序.安全功能 IPC:In ...