My Calendar II - Solution & Explanation
Problem Statement
You are implementing a program to use as your calendar. We can add a new event if adding the event will not cause a triple booking.
A triple booking happens when three events have some non-empty intersection (i.e., some moment is common to all the three events.).
The event can be represented as a pair of integers startTime and endTime that represents a booking on the half-open interval [startTime, endTime), the range of real numbers x such that startTime <= x < endTime.
Implement the MyCalendarTwo class:
MyCalendarTwo()Initializes the calendar object.boolean book(int startTime, int endTime)Returnstrueif the event can be added to the calendar successfully without causing a triple booking. Otherwise, returnfalseand do not add the event to the calendar.
Example 1:
Input ["MyCalendarTwo", "book", "book", "book", "book", "book", "book"] [[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]] Output [null, true, true, true, false, true, true] Explanation MyCalendarTwo myCalendarTwo = new MyCalendarTwo(); myCalendarTwo.book(10, 20); // return True, The event can be booked. myCalendarTwo.book(50, 60); // return True, The event can be booked. myCalendarTwo.book(10, 40); // return True, The event can be double booked. myCalendarTwo.book(5, 15); // return False, The event cannot be booked, because it would result in a triple booking. myCalendarTwo.book(5, 10); // return True, The event can be booked, as it does not use time 10 which is already double booked. myCalendarTwo.book(25, 55); // return True, The event can be booked, as the time in [25, 40) will be double booked with the third event, the time [40, 50) will be single booked, and the time [50, 55) will be double booked with the second event.
Constraints:
0 <= start < end <= 109- At most
1000calls will be made tobook.
Approach Overview
Problem Overview: You need to design a calendar that supports booking events represented as half-open intervals [start, end). A booking is allowed if it does not create a triple booking. Double bookings are fine, but three overlapping events at the same time must be rejected.
Approach 1: Using Two Lists for Overlapping Intervals (O(n) per booking, O(n) space)
This approach tracks two lists: bookings (all accepted events) and overlaps (intervals that are already double booked). When a new event arrives, first check if it overlaps with anything in overlaps. If it does, the booking would create a triple overlap, so reject it immediately.
If it passes that check, iterate through existing bookings. For every interval that intersects with the new one, compute the intersection and add that range to overlaps. This records the newly created double-booked region. Finally, add the new interval to bookings. The key insight: instead of tracking counts everywhere, explicitly track the ranges where double booking already exists.
This method relies heavily on interval intersection logic and sequential scans using an array. Each booking may compare with all previous events, giving O(n) time per operation and O(n^2) total across all calls in the worst case.
Approach 2: Segment Tree for Interval Overlaps (O(log C) per booking, O(n log C) space)
When the time range becomes large (up to 10^9), scanning intervals repeatedly becomes inefficient. A dynamic segment tree solves this by storing the maximum booking count for each range. Each node represents a segment of time and keeps track of the maximum overlap inside that range.
For every booking request, query the tree to check the maximum overlap in [start, end). If the value is already 2, adding another event would create a triple booking, so reject it. Otherwise, update the range by incrementing its count. Lazy propagation allows efficient range updates without expanding the entire tree.
This method treats the problem as a range frequency update problem similar to sweep-line or prefix sum techniques, but implemented with a tree so queries stay logarithmic. Each booking runs in O(log C) time where C is the coordinate range.
Recommended for interviews: The two-list interval method is the most commonly expected answer. It is short, easy to reason about, and demonstrates clear understanding of interval overlaps. The segment tree approach shows deeper knowledge of advanced data structures and range queries, which can impress in system-heavy or follow-up interview questions.
Approach 1: Approach 1: Using Two Lists for Overlapping Intervals
In this approach, we maintain two separate lists: `single_booked` for bookings that have been added without conflicts, and `double_booked` for intervals where two events overlap. To add a new booking:
- First, check if it causes a triple booking by comparing it with the existing `double_booked` intervals. If any interval in `double_booked` overlaps with the new booking, it indicates a triple booking.
- If no triple booking is detected, proceed to update the lists:
- Check the new booking against `single_booked`. If there's an overlap with an interval in `single_booked`, this represents a double booking, and the overlapping part should be added to `double_booked`.
- Finally, add the current booking to `single_booked`.
The C solution defines two lists to store the single_booked and double_booked intervals. The `book` function checks for triple bookings by testing overlaps with double_booked, then adds any necessary doubles before adding the event to the single_booked list.
Complexity
Time Complexity: O(N^2) because for each booking, we might need to check with all existing ones.
Space Complexity: O(N) to store all bookings.
Approach 2: Approach 2: Segment Tree for Interval Overlaps
In this approach, we use a segment tree to efficiently keep track of overlapping intervals. By maintaining a segment tree, we can:
- Efficiently query the total number of active bookings over any particular interval to avoid triple bookings.
- Allow immediate updates whenever a new booking starts or ends, thus adjusting the tree in place.
This approach is optimal for datasets with large integer boundaries due to the logarithmic nature of segment trees for both update and query operations.
The C++ solution uses a `map` to simulate a segment tree on a line sweep basis. As intervals are booked or end, we increment or decrement from the timeline, respectively. The `book` method tracks active bookings to ensure it never surpasses two overlapping intervals.
Code
C++
Java
Python
C#
JavaScript
Complexity
Time Complexity: O(N log N) due to map operations.
Space Complexity: O(N) for map storage.
Approach 3: Difference Array
We can use the concept of a difference array to record the booking status at each time point. Then, we traverse all the time points and count the booking status at the current time point. If the number of bookings exceeds 2, we return false. Otherwise, we return true.
The time complexity is O(n^2), and the space complexity is O(n), where n is the number of bookings.
Code
Python
Java
C++
Go
TypeScript
JavaScript
Approach 4: Segment Tree
A segment tree divides the entire interval into multiple non-contiguous subintervals, with the number of subintervals not exceeding log(width). To update the value of an element, only log(width) intervals need to be updated, and these intervals are all contained within a larger interval that includes the element. When modifying intervals, a lazy mark is used to ensure efficiency.
- Each node of the segment tree represents an interval;
- The segment tree has a unique root node representing the entire statistical range, such as
[1, N]; - Each leaf node of the segment tree represents a unit interval of length 1,
[x, x]; - For each internal node
[l, r], its left child is[l, mid]and its right child is[mid + 1, r], wheremid = \lfloor(l + r) / 2\rfloor(i.e., floor division).
For this problem, the segment tree nodes maintain the following information:
- The maximum number of bookings within the interval
v - Lazy mark
add
Since the time range is 10^9, which is very large, we use dynamic node creation.
The time complexity is O(n times log n), and the space complexity is O(n). Here, n is the number of bookings.
Code
Python
Java
C++
Go
TypeScript
JavaScript
Complexity Comparison
| Approach | Complexity |
|---|---|
| Approach 1: Using Two Lists for Overlapping Intervals | Time Complexity: O(N^2) because for each booking, we might need to check with all existing ones. |
| Approach 2: Segment Tree for Interval Overlaps | Time Complexity: O(N log N) due to map operations. |
| Difference Array | — |
| Segment Tree | — |
Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Two Lists for Overlapping Intervals | O(n) per booking, O(n^2) total | O(n) | Best for interviews and moderate constraints; simple logic using interval comparisons |
| Segment Tree with Lazy Propagation | O(log C) per booking | O(n log C) | When time coordinates are large and frequent range queries or updates are required |
Video Solution
My Calendar II - Leetcode 731 - Python • NeetCodeIO • 13,849 views views
Watch 9 more video solutions →Frequently Asked Questions
Is My Calendar II easy or hard?
My Calendar II Python/Java solution
How to solve My Calendar II in O(n)?
What is the best approach for My Calendar II?
Is My Calendar II asked at Google/Amazon/Meta?
What data structure is used in My Calendar II?
What is the time complexity of My Calendar II?
Ready to solve this problem?
Practice My Calendar II with our built-in code editor and test cases.
Practice on FleetCodeTable of Contents
Practice this problem
Open in Editor