LeetCode 729 - My Calendar I


Related: LeetCode 729 - My Calendar I
LeetCode 731 - My Calendar II
LeetCode 732 - My Calendar III
https://leetcode.com/problems/my-calendar-i/solution/
Implement a MyCalendar class to store your events. A new event can be added if adding the event will not cause a double booking.
Your class will have the 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.
double booking happens when two events have some non-empty intersection (ie., there is some time that is common to both events.)
For each call to the method MyCalendar.book, return true if the event can be added to the calendar successfully without causing a double 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(15, 25); // returns false
MyCalendar.book(20, 30); // returns true
Explanation: 
The first event can be booked.  The second can't because time 15 is already booked by another event.
The third event can be booked, as the first event takes every time less than 20, but not including 20.
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].

  • X. Using TreeMap
    • Time Complexity (Java): O(N \log N), where N is the number of events booked. For each new event, we search that the event is legal in O(\log N) time, then insert it in O(1) time.
    • Time Complexity (Python): O(N^2) worst case, with O(N \log N) on random data. For each new event, we insert the event into our binary tree. As this tree may not be balanced, it may take a linear number of steps to add each event.
    • Space Complexity: O(N), the size of the data structures used.
    X. https://leetcode.com/problems/my-calendar-i/discuss/109473/JAVA-Simple-6-line-Solution-TreeMap-lowerEntry
        TreeMap tm;
    
        public MyCalendar() {
            tm = new TreeMap<Integer, Integer>();
        }
        
        public boolean book(int start, int end) {
            Map.Entry<Integer, Integer> entry = tm.lowerEntry(end);
            if (entry != null && entry.getValue() > start) return false;
            tm.put(start, end);
            return true;
        }

    https://leetcode.com/problems/my-calendar-i/discuss/109462/Java-8-liner-TreeMap
        TreeMap<Integer, Integer> calendar;
    
        public MyCalendar() {
            calendar = new TreeMap<>();
        }
    
        public boolean book(int start, int end) {
            Integer floorKey = calendar.floorKey(start);
            if (floorKey != null && calendar.get(floorKey) > start) return false;
            Integer ceilingKey = calendar.ceilingKey(start);
            if (ceilingKey != null && ceilingKey < end) return false;
    
            calendar.put(start, end);
            return true;
        }
        TreeMap<Integer, Integer> calendar;

        MyCalendar() {
            calendar = new TreeMap();
        }

        public boolean book(int start, int end) {
            Integer prev = calendar.floorKey(start),
                    next = calendar.ceilingKey(start);
            if ((prev == null || calendar.get(prev) <= start) &&
                    (next == null || end <= next)) {
                calendar.put(start, end);
                return true;
            }
            return false;
        }
    https://leetcode.com/problems/my-calendar-i/discuss/109475/JavaC++-Clean-Code-with-Explanation
        TreeSet<int[]> books = new TreeSet<int[]>((int[] a, int[] b) -> a[0] - b[0]);
    
        public boolean book(int s, int e) {
            int[] book = new int[] { s, e }, floor = books.floor(book), ceiling = books.ceiling(book);
            if (floor != null && s < floor[1]) return false; // (s, e) start within floor
            if (ceiling != null && ceiling[0] < e) return false; // ceiling start within (s, e)
            books.add(book);
            return true;
        }
    X.
    https://leetcode.com/problems/my-calendar-i/discuss/109493/A-much-smarter-binarySearch-algorithm
    // algorithm 2017/11/19: keep intervals sorted, but we do not really care whether it is an accurate match; so long there is an overlapping, we deem the two intervals equals
    public MyCalendar() {
        
    }
    
    public boolean book(int start, int end) {
        assert start < end;
        Interval interval = new Interval(start, end-1);
        int foundIndex = Collections.binarySearch(entries, interval);
        if (foundIndex >= 0) {
            return false;
        }
        // insert and merge
        int insertPos = -(foundIndex+1);//\\
        entries.add(insertPos, interval);
        // optionally merge
        return true;
    }
    
    private List<Interval> entries = new ArrayList<>();
    
    class Interval implements Comparable<Interval> {
        public Interval(int start, int end) {
            this.start = start;
            this.end   = end;
        }
        public int compareTo(Interval anotherInterval) {
            if (this.end < anotherInterval.start) {
                return -1;
            } else if (this.start > anotherInterval.end) {
                return 1;
            } else {
                return 0;       // intervals are equal so long they overlap
            }
        }
        
        int start;  // inclusive
        int end;    // inclusive
    }

    // sort by end
    private List<Interval> intervals = new ArrayList<>();

    public MyCalendar() {
    }

    public boolean book(int start, int end) {
    if (intervals.isEmpty()) {
    intervals.add(new Interval(start, end));
    return true;
    }
    int pos = Collections.binarySearch(intervals, new Interval(start, end));
    if (pos >= 0) {
    return false;
    }
    pos = -pos - 1;
    // defensive programming
    // even if think it may be always >=0, it's better to add the extra condition,
    // as it may be not that case
    if (pos - 1 >= 0 && intervals.get(pos - 1).end > start) {
    // not >= error prone
    return false;
    }
    if (pos < intervals.size() && intervals.get(pos).start < end) {
    // not >= error prone
    return false;
    }
    if (pos < intervals.size()) { // not -1
    intervals.add(pos, new Interval(start, end));
    } else {
    intervals.add(new Interval(start, end));
    }
    return true;
    }

    private static class Interval implements Comparable<Interval> {
    public final int start, end;

    public Interval(int start, int end) {
    super();
    this.start = start;
    this.end = end;
    }

    @Override
    public String toString() {
    return "Interval [start=" + start + ", end=" + end + "]";
    }

    @Override
    public int compareTo(Interval other) {
    // if (this.end == other.end) {
    // // \\
    // return Integer.compare(this.start, other.start);
    // }
    return Integer.compare(this.end, other.end);
    }

    }

    • Time Complexity: O(N^2), where N is the number of events booked. For each new event, we process every previous event to decide whether the new event can be booked. This leads to \sum_k^N O(k) = O(N^2)complexity.
    • Space Complexity: O(N), the size of the calendar.
        List<int[]> calendar;

        MyCalendar() {
            calendar = new ArrayList();
        }

        public boolean book(int start, int end) {
            for (int[] iv: calendar) {
                if (iv[0] < end && start < iv[1]) return false;//\\
            }
            calendar.add(new int[]{start, end});
            return true;
        }


    X. https://www.cnblogs.com/FannyChung/p/7896415.html
    对于不能重合的事件,可以利用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;
        }

    Labels

    LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

    Popular Posts