用BST解决729. My Calendar I 731. My Calendar II 732. My Calendar III

My Calendar的book方法实现指定开始时间、结束时间,在重叠次数要求不同的情况下怎么实现。
729 My Calendar I 要求任意两个事件之间不能重叠。如果要插入的事件和已经插入的事件不重叠,则插入;否则不插入。
731 MyCalendar II 要求任意三个时间之间不能重叠,但两个事件可以重叠。同样,如果满足要求,则事件可以插入,否则不能插入。
732 MyCalendar III 则是要求返回插入当前事件之后,整个Calendar中重叠次数最多是多少。

729 My Calendar I

要求任意两个事件之间不能重叠,可以利用二叉查找树BST。每个节点代表一个事件,包含start,end。如果要插入的事件范围,全部在当前节点左侧,或者右侧,则可以插入。否则不可以插入。

 class MyCalendarV3 {class Node{int start,end;Node left,right;Node(int start,int end){this.start  = start;this.end = end;}}Node root;public boolean book(int start, int end) {if(insertable(start,end,root)){root = insert(start,end,root);return true;}return false;}private Node insert(int start, int end, Node cur) {if(cur==null) return new Node(start,end);if(start>=cur.end) {cur.right = insert(start, end, cur.right);}else if(end <= cur.start) {cur.left = insert(start, end, cur.left);}return cur;}private boolean insertable(int start, int end, Node cur) {if(cur==null) return true;if(start>=cur.end) {return insertable(start, end, cur.right);}else if(end <= cur.start) {return insertable(start, end, cur.left);}return false;}
}

731 My Calendar II

要求任意三个时间之间不能重叠,但两个事件可以重叠。在上面解题的基础上,需要将有重叠区域的做节点分裂,并且标记是不是已经重复。如果已经重复的节点,再次遇到重叠,则不允许插入。这个节点分裂,则是整个过程中比较复杂的部分。
例如:MyCalendar.book(10, 20); MyCalendar.book(50, 60); 之后树应该是这样的。
这里写图片描述
当要插入(10,40)的时候,首先会遇到与curNode(10,20)节点重叠。节点分裂为[10,10),[10,20),[20,40)三个部分。[10,10)插入curNode的左节点,[20,40)插入curNode的右节点。在插入右节点的时候又需要与已经存在的右节点(50,60)做比较。[20,40)作为节点(50,60)的左节点插入。如下图所示。节点(10,20)被标记为overlap=true。下次再碰到这个区域的重叠的事件,则可以直接返回false。
这里写图片描述
当然节点[10,10)是没有意义的。既包含10,又不包含10,是空集应该去掉。
这里写图片描述
以上展示了一个节点分裂的过程。插入的start,end;当前节点的curNode.left,curNode.right,这四个数之间有大小关系。如果按照从小到大分别记为n1,n2,n3,n4,则(n1,n2)是curNode的左子树;(n3,n4)作为curNode的右子树;curNode.left=n2,curNode.right=n3。
这里写图片描述

class MyCalendarTwoV2 {class Node{int start,end;boolean overlap;Node left,right;Node(int start,int end){this.start  = start;this.end = end;}}Node root;public MyCalendarTwoV2() {}public boolean book(int start, int end) {if(!insertable(start,end,root)){return false;}root = insert(start,end,root);return true;}private Node insert(int start, int end, Node cur) {if(start>=end) return cur;if(cur==null){return new Node(start,end);}if(start >= cur.end) {cur.right = insert(start,end,cur.right);}else if(end <= cur.start){cur.left = insert(start,end,cur.left);}else{cur.overlap = true;int a = Math.min(start, cur.start);int b = Math.max(start, cur.start);int c = Math.min(end, cur.end);int d = Math.max(end, cur.end);cur.left = insert(a,b,cur.left);cur.right = insert(c,d,cur.right);cur.start = b;cur.end = c;}return cur;}/*** 判断start,end 是否可插入* @param start* @param end* @param curNode* @return*/private boolean insertable(int start, int end, Node cur) {if(start>=end) return true;if(cur==null) return true;if(start >= cur.end) {return insertable(start,end,cur.right);}else if(end <= cur.start){return insertable(start,end,cur.left);}else{if(cur.overlap){return false;}else{if(start>=cur.start && end <= cur.end){return true;}else{return insertable(start,cur.start,cur.left) && insertable(cur.end,end,cur.right);}}}}
}

732 My Calendar III

要求返回插入当前事件之后,整个Calendar中重叠次数最多是多少。在上题基础上,把Boolean 变量换成计数的int类型。当本区域发生一次重叠,则计数加1。
对于分裂产生的节点,次数不能简单设置为1。
这里写图片描述
参考上图,分析一下分裂插入的左子树部分。假设curNode当前区域已经出现了count次。如果分裂后的区域是[start,curNode.left)这是一个新的区域,次数为1;如果分裂后是[curNode.left,start)那么次数就应该是count,因为[curNode.left,start)肯定包含在[curNode.left,curNode.right)范围内。同理分析一下右子树部分。

class MyCalendarThree {class Node{int start,end;int k = 1;Node left,right;Node(int start,int end,int k){this.start  = start;this.end = end;this.k = k;}}Node root;int maxK=1;public MyCalendarThree() {}/*** * @param start* @param end* @return*/public int book(int start, int end) {root = insert(start,end,root,1);return maxK;}private Node insert(int start, int end, Node cur,int val) {if (start >= end)return cur;if (cur == null) {return new Node(start, end,val);}if (start >= cur.end) {cur.right = insert(start, end, cur.right,val);} else if (end <= cur.start) {cur.left = insert(start, end, cur.left,val);} else {int a = Math.min(start, cur.start);int b = Math.max(start, cur.start);int c = Math.min(end, cur.end);int d = Math.max(end, cur.end);//细节是这里cur.left = insert(a, b, cur.left,start<=cur.start?val:cur.k);cur.right = insert(c, d, cur.right,end>=cur.end?val:cur.k);cur.start = b;cur.end = c;cur.k +=val;}maxK = Math.max(maxK, cur.k);return cur;}
}

My Calendar的其他思路

BST只是一种解决思路。还可以使用其他。例如729 可以使用TreeMap,判断重叠区域。731 可以在利用729类的基础上,判断是否有重叠区域。732还有一种timeline的思路。把所有区域看做是一条线上的点。这种思路非常赞。遇到start,值加1;遇到end,值减1。求得在一个线段内重复的次数。
例如:MyCalendarThree.book(10, 20); // returns 1
MyCalendarThree.book(50, 60); // returns 1
MyCalendarThree.book(10, 40); // returns 2
这里写图片描述

[10,20)2次
[20,40)1次
[40,50)0次
[50,60)1次

class MyCalendarThreeV2 {private TreeMap<Integer, Integer> timeline = new TreeMap<>();public int book(int s, int e) {timeline.put(s, (timeline.get(s)!=null?timeline.get(s):0) + 1); // 1 new event will be// starting at [s]timeline.put(e, (timeline.get(e)!=null?timeline.get(e):0) - 1); // 1 new event will be// ending at [e];int ongoing = 0, k = 0;for (int v : timeline.values())k = Math.max(k, ongoing += v);return k;}
}

参考资料:
网页1
网页2
网页3
网页4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/424808.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[转载]抓大放小,要事为先

最近看到了swing框架&#xff0c;细节颇多。细细看来效率很低&#xff0c;偶然找到了这篇文章&#xff0c;恩确实有道理&#xff1b;以下&#xff1b; 对待人生的任何事情都要&#xff1a;抓大放小&#xff0c;要事为先 对于一个以前从来没有接触过java的人&#xff0c;java无疑…

第三十七期:如果你这样回答“什么是线程安全”,面试官都会对你刮目相看

6月12日 以下文章来源于编程新说 &#xff0c;作者编程新说李新杰 有读者跟我说&#xff0c;喜欢看我的文章&#xff0c;说很容易读&#xff0c;我确实在易读性上花费的心思不亚于在内容上。因为我不喜欢一上来就堆很多东西&#xff0c;而且把简单的东西搞得复杂人人都会&…

第三十八期:如何在Windows 10上使用Windows Update目录驱动程序安装打印机

尽管Win10能够自动设置大多数打印机&#xff0c;但有时Windows Update可能会在安装设备驱动程序时遇到问题-尤其是在添加较旧的打印机时。 作者&#xff1a;佚名来源&#xff1a;Win10系统之家 图片来源&#xff1a;伏天氏(m.futianshuwu.com) 伏天书屋(futianshuwu.com)10月…

MySQL 表和列的注释

像代码一样&#xff0c;可以为表以及表中的列添加注释&#xff0c;方便其他人知晓其功能。对于一些字段&#xff0c;在经过一定时间后&#xff0c;创建者未必也能想起其具体的含意&#xff0c;所以注释显得尤为重要。 注释的添加 注释的添加是通过在定义表或列的时候在末尾加上…

376 Wiggle Subsequence 贪心解法以及证明

376. Wiggle Subsequence 题目理解 给定一个数组&#xff0c;相邻两个数计算差值。差值排成的序列是正负相间的&#xff0c;那这个数组就是一个wiggle 数组。例如数组[1,7,4,9,2,5]&#xff0c;差值序列是(6,-3,5,-7,3)。原数组用坐标轴表示如下。 思路是&#xff1a;在一段…

【数据结构与算法】【算法思想】动态规划

贪心算法 回溯算法 分治算法 动态规划 贪心&#xff1a;一条路走到黑&#xff0c;就一次机会&#xff0c;只能哪边看着顺眼走哪边 回溯&#xff1a;一条路走到黑&#xff0c;无数次重来的机会&#xff0c;还怕我走不出来 (Snapshot View) 动态规划&#xff1a;拥有上帝视角&am…

第六十七期:Python爬虫44万条数据揭秘:如何成为网易音乐评论区的网红段子手

获取数据,其实逻辑并不复杂&#xff1a;爬取歌单列表里的所有歌单url、进入每篇歌单爬取所有歌曲url&#xff0c;去重、进入每首歌曲首页爬取热评&#xff0c;汇总。 作者&#xff1a;嗨学python来源&#xff1a;今日头条 获取数据 其实逻辑并不复杂&#xff1a; 爬取歌单列…

第一阶段SCRUM冲刺 08

昨天的成就&#xff1a;实现任务查找模块。感觉到了硬件支持对软件编程的重要性。 遇到的难题&#xff1a;电脑出现卡顿&#xff0c;编程工具十分卡&#xff0c;重启电脑好几次解决这个问题。电脑也是需要休息的。 今天的任务&#xff1a;进行资料上传模块&#xff1b;发布任务…

array专题7

714 Best Time to Buy and Sell Stock with Transaction Fee 思路 首先是暴力枚举。考虑在第idx天能做的操作&#xff1a;买&#xff1f;卖&#xff1f;不操作&#xff1f; /*** 暴力枚举* * param prices* param fee* return*/public int maxProfitV99(int[] prices, int f…

第三十九期:收藏 | 第一次有人把“分布式事务”讲的这么简单明了

不知道你是否遇到过这样的情况&#xff0c;去小卖铺买东西&#xff0c;付了钱&#xff0c;但是店主因为处理了一些其他事&#xff0c;居然忘记你付了钱&#xff0c;又叫你重新付。 作者&#xff1a;咖啡拿铁来源 又或者在网上购物明明已经扣款&#xff0c;但是却告诉我没有发…

【小技巧】字符char与整型int的相互转换

char转int char与int的相互转化&#xff0c;联想ASCII码&#xff0c;字符‘0’对应的值为48&#xff0c;所以不能直接加减‘ ’ char ch9; int ch_intch-0;//此时ch_int9int转char int i9&#xff1b; char i_chi0;//此时i_ch9必须牢记的ASCII

array专题8

670 Maximum Swap 思路&#xff1a;先把整数分解成一个一个的数&#xff0c;从0-n放着从最低位到最高位的数字。例如2376变成数组[6,7,3,2]。假设要替换的是最高位n-1,从0到n-2中查找是否有比nums[n-1]大的元素&#xff1b;如果有则替换&#xff0c;否则继续考虑替换n-2位。比…

nginx 编译安装

安装 Nginx 所依赖的基本服务&#xff1a; yum -y install gcc gcc-c automake pcre pcre-devel zlip zlib-devel openssl openssl-devel 官网 http://nginx.org 下载安装包 编译nginx make (可参考http://nginx.org/en/docs/configure.html) ./configure --prefix/data1/se…

第四十期:九个对Web开发者最有用的Python包,掌握这些,工资至少能涨涨

Matplotlib&#xff0c;正如其名称所暗示的那样&#xff0c;是一个用来绘制数学函数和模型的库;扩展了Numpy的作用&#xff0c;Matplotlib可以只用几行代码来创建图&#xff0c;条形图&#xff0c;散点图等诸多视觉表现。 作者&#xff1a;Python之眼来源&#xff1a;今日头条…

array专题9

新的一周&#xff0c;新的专题。array的中等难度的题目快要结束了。能感觉到进步&#xff0c;也依然能感觉到吃力。加油。 31 Next Permutation 思路&#xff1a;读懂了题意&#xff0c;知道是要求下一个排列数是什么。如果已经到最后一个了&#xff0c;那就返回最小的那个。…

[Leetcode][第214题][JAVA][最短回文串][KMP][RK]

【问题描述】[中等] 【解答思路】 1. 字符串哈希 复杂度 class Solution {public String shortestPalindrome(String s) {int n s.length();int base 131, mod 1000000007;int left 0, right 0, mul 1;int best -1;for (int i 0; i < n; i) {left (int) (((long)…

坏掉的项链Broken Necklace

题目描述 你有一条由N个红色的&#xff0c;白色的&#xff0c;或蓝色的珠子组成的项链(3<N<350)&#xff0c;珠子是随意安排的。 这里是 n29 的二个例子: 第一和第二个珠子在图片中已经被作记号。 图片 A 中的项链可以用下面的字符串表示&#xff1a; brbrrrbbbrrrrrbrrb…

689 Maximum Sum of 3 Non-Overlapping Subarrays

题目 思路&#xff1a;首先是长度为k的子数组的和。这个好计算。题目要求返回的是三个和最大的子数组的第一个数字的下标。下标要尽可能小。如果只要求这样&#xff0c;题目就很简单了。还有个要求是各个子数组不重叠。要想不重叠首先得要求下标不重叠。子数组1下标是:0,1,2&a…

[Leetcode][第557题][JAVA][反转字符串中的单词 III][遍历][String函数]

【问题描述】[简单] 【解答思路】 1. 遍历 开辟一个新字符串。然后从头到尾遍历原字符串&#xff0c;直到找到空格为止&#xff0c;此时找到了一个单词&#xff0c;并能得到单词的起止位置。随后&#xff0c;根据单词的起止位置&#xff0c;可以将该单词逆序放到新字符串当中…

第七十二期:爬虫爬的好,牢饭吃到饱?

前几天分享的一篇《只因写了一段爬虫&#xff0c;公司200多人被抓!》相信大家看了后都会发问&#xff0c;我只是个写爬虫的&#xff0c;跟我有什么关系?到底什么样的爬虫才不犯法?今天这篇会解答你所有的疑问。 作者&#xff1a;技术领导力 前几天分享的一篇爬虫被抓相信大…