Before attempting this problem, you should be comfortable with:
Interval Overlap Detection - Understanding when two intervals conflict using start and end time comparisons
Binary Search Trees - Organizing intervals in a tree structure for efficient insertion and lookup
Binary Search - Finding insertion points in sorted collections to efficiently check neighbors
1. Iteration
Intuition
Two events overlap if one starts before the other ends and vice versa. For each new booking request, we need to check whether it conflicts with any existing event. We can store all booked events in a list and iterate through them to detect overlaps. If no conflict is found, we add the new event to the list.
Algorithm
Maintain a list of booked events, where each event is stored as a (start, end) pair.
When book(startTime, endTime) is called:
Iterate through all existing events.
For each event (start, end), check if startTime < end and start < endTime. If both conditions are true, there is an overlap, so return false.
If no overlap is found, append the new event to the list and return true.
classMyCalendar:def__init__(self):
self.events =[]defbook(self, startTime:int, endTime:int)->bool:for start, end in self.events:if startTime < end and start < endTime:returnFalse
self.events.append((startTime, endTime))returnTrue
Time complexity: O(n) for each book() function call.
Space complexity: O(n)
2. Binary Search Tree
Intuition
We can organize events in a binary search tree where each node represents a booked interval. The tree is ordered by start times: intervals that end before a node's start time go to the left subtree, and intervals that start after a node's end time go to the right subtree. When inserting a new interval, we traverse the tree to find where it fits without overlapping any existing node. If it overlaps with a node during traversal, we reject it.
Algorithm
Each tree node stores (start, end) and has left and right children.
When book(startTime, endTime) is called:
If the tree is empty, create the root node with this interval and return true.
Otherwise, traverse from the root:
If endTime <= node.start, the new interval belongs in the left subtree.
If startTime >= node.end, the new interval belongs in the right subtree.
Otherwise, there is an overlap, so return false.
When reaching a null child pointer, insert the new node there and return true.
Time complexity: O(logn) in average case, O(n) in worst case for each book() function call.
Space complexity: O(n)
3. Binary Search + Ordered Set
Intuition
By keeping events sorted by start time, we can use binary search to quickly find where a new event would be inserted. We only need to check the immediate neighbors (the event just before and just after the insertion point) for potential overlaps. If the previous event ends after our start time, or the next event starts before our end time, we have a conflict. This gives us logarithmic search time per booking.
Algorithm
Maintain a sorted collection of events ordered by start time.
When book(startTime, endTime) is called:
Use binary search to find the idx for the new event.
Check the event at the previous index (if it exists): if its end time is greater than startTime, return false.
Check the event at the current idx (if it exists): if its start time is less than endTime, return false.
If no conflicts, insert the new event at the correct position and return true.
Time complexity: O(logn) for each book() function call.
Space complexity: O(n)
Common Pitfalls
Using Incorrect Overlap Condition
A common mistake is using <= instead of < when checking for overlaps. The correct overlap condition is startTime < end && start < endTime. Since intervals are half-open [start, end), an event ending exactly when another starts (e.g., [10, 20) and [20, 30)) does not constitute an overlap. Using <= would incorrectly reject valid adjacent bookings.
Forgetting to Handle Edge Cases for Empty Calendar
When implementing the BST or binary search approach, forgetting to handle the case when the calendar is empty can lead to null pointer exceptions or incorrect behavior. Always check if the root is null (BST) or if the events list is empty before performing searches or comparisons.
Off-by-One Errors in Binary Search Neighbor Checks
In the binary search with ordered set approach, a subtle bug occurs when checking neighbors at the insertion point. You must verify that idx - 1 exists before accessing the previous event, and that idx is within bounds before accessing the next event. Failing to perform these boundary checks results in index out of bounds errors for edge cases like inserting at the beginning or end of the sorted list.