用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。
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)范圍內。同理分析一下右子樹部分。
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次
參考資料:
網頁1
網頁2
網頁3
網頁4
總結
以上是生活随笔為你收集整理的用BST解决729. My Calendar I 731. My Calendar II 732. My Calendar III的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS Regex
- 下一篇: 【数据结构与算法】哈希算法