My Calendar III

Updated on 19 June, 2025
My Calendar III header image

Problem Statement

The problem revolves around tracking overlapping intervals or events in a simulated calendar system and determining the maximum level of overlap at any given time, referred to as k-booking. Specifically, a k-booking occurs when k distinct events share at least one common time point.

To manage and query these intervals, you are required to implement a class, MyCalendarThree, which supports:

  1. MyCalendarThree() - Constructor that initializes the new object.
  2. int book(int startTime, int endTime) - Method to add a new event to the calendar that starts at startTime and ends just before endTime. Post each booking, this function should return the maximum number k which indicates the highest number of overlapping events until that point in time.

The intervals are defined using a half-open interval notation [startTime, endTime), which includes startTime but excludes endTime.

Examples

Example 1

Input:

["MyCalendarThree", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]

Output:

[null, 1, 1, 2, 3, 3, 3]

Explanation:

MyCalendarThree myCalendarThree = new MyCalendarThree();
myCalendarThree.book(10, 20); // return 1
myCalendarThree.book(50, 60); // return 1
myCalendarThree.book(10, 40); // return 2
myCalendarThree.book(5, 15);  // return 3
myCalendarThree.book(5, 10);  // return 3
myCalendarThree.book(25, 55); // return 3

Constraints

  • 0 <= startTime < endTime <= 10⁹
  • At most 400 calls will be made to book.

Approach and Intuition

To handle the bookings and check the overlaps effectively, the following approach can be adopted:

  1. Timeline Sweep with Counters: Treat each booking as two events:

    • +1 at startTime (event starts)
    • -1 at endTime (event ends) Maintain a counter map that tracks how many events are active at any given time.
  2. Booking Operation:

    • On every book(start, end) call:

      • Increment the value at start and decrement at end in a TreeMap or SortedDict.
      • Iterate over the time points in order and maintain a running sum of active events.
      • Track the peak of this running sum, which gives the updated max overlap k.
  3. Why it Works Efficiently:

    • Since we only make at most 400 calls, and we only update/query a limited set of time points, this approach runs in acceptable time.
    • Using a TreeMap-like structure keeps insertions and iteration in O(log N) or O(N) where N is the number of unique time points.
  4. Illustration: For bookings like:

    • [10, 20] → overlap 1
    • [10, 40] → overlaps with previous → overlap 2
    • [5, 15] → overlaps both → peak overlap 3

This design efficiently simulates the booking system and dynamically tracks the maximum concurrent events.

Solutions

  • C++
  • Java
  • Python
cpp
class CalendarMaxOverlap {
private:
    map<int, int> events;
    int maxOverlap;

public:
    CalendarMaxOverlap() {
        events[0] = 0;
        events[1000000001] = 0;
        maxOverlap = 0;
    }

    void insertPoint(int point) { events[point] = (--events.upper_bound(point))->second; }

    int bookEvent(int start, int end) {
        insertPoint(start), insertPoint(end);
        for (auto iter = events.find(start); iter->first < end; ++iter) {
            maxOverlap = max(maxOverlap, ++(iter->second));
        }
        return maxOverlap;
    }
};

This solution implements a data structure named CalendarMaxOverlap, which is designed to manage booking intervals and finding the maximum overlap among them using C++ programming language. This is particularly useful when dealing with scheduling problems where conflicts might occur due to overlapping time slots.

The class uses a private map named events to store the changes in active bookings at various time points. It also maintains an integer maxOverlap to keep track of the maximum number of overlapping events at any point in time.

  • The constructor initializes the map with two entries that define the range of valid bookings, effectively initializing the system with boundaries and no overlap.
  • The method insertPoint ensures that every new point in time where an event starts or ends is properly tracked in the events map, inheriting the active count from the previous closest time point.
  • The bookEvent method performs the main functionality:
    1. Inserts the start and end points of a new event.
    2. Iterates from the start to the end point, updating the overlap count for each point and adjusting maxOverlap if the current overlap exceeds the previously recorded maximum.
    3. Returns the maxOverlap value, which after booking is the maximum overlap among all bookings.

This implementation provides an efficient mechanism to track and update overlaps, making use of the efficient logarithmic time complexity operations of std::map for insertion and searching.

java
class ScheduleOverlapping {
    private TreeMap<Integer, Integer> timeline;
    private int maxOverlap;

    public ScheduleOverlapping() {
        timeline = new TreeMap<>();
        timeline.put(0, 0);
        maxOverlap = 0;
    }

    public void createSplitPoint(int point) {
        Integer left = timeline.floorKey(point);
        Integer right = timeline.ceilingKey(point);
        if (right != null && right == point)
            return;
        timeline.put(point, timeline.get(left));
    }

    public int bookEvent(int start, int end) {
        createSplitPoint(start);
        createSplitPoint(end);
        for (var interval : timeline.subMap(start, true, end, false).entrySet()) {
            maxOverlap = Math.max(maxOverlap, interval.setValue(interval.getValue() + 1) + 1);
        }
        return maxOverlap;
    }
}

Implement a class named ScheduleOverlapping in Java to manage events in a timeline and calculate the maximum overlapping events occuring simultaneously.

  • Start by initializing a TreeMap named timeline to manage the event start and end points with their counts.

  • maxOverlap is an integer that keeps track of the highest number of overlapping intervals.

  • The constructor ScheduleOverlapping() initializes the timeline by placing an initial boundary marker at the point 0 with zero active events.

  • createSplitPoint(int point) method is critical for adding new points to the timeline:

    • Identify the nearest left and right points around the specified event point using floorKey and ceilingKey.
    • If the exact point already exists (right == point), no action is taken.
    • Otherwise, the current event count from the immediate left point is extended to this new point.
  • bookEvent(int start, int end) method handles the booking of an event:

    • Create necessary split points at the start and end of the event using the createSplitPoint method.
    • Iterate over the intervals between start and end, updating and checking overlaps for maximum value encountered so far.
  • Return the calculated maxOverlap each time an event is booked, providing the current maximum number of simultaneous events after each booking.

The solution leverages the sorted map provided by TreeMap to efficiently manage updates and queries to the timeline, making it optimal for scenarios where frequent changes in event times and calculations of maximum overlaps are needed.

python
from sortedcontainers import SortedList

class EventScheduler:

    def __init__(self):
        self.events = SortedList([[0, 0]])  # initialize with a default event
        self.max_overlap = 0

    def insert_point(self, point: int) -> None:
        position = self.events.bisect_left([point, 0])
        if position < len(self.events) and self.events[position][0] == point:
            return
        self.events.add([point, self.events[position - 1][1]])

    def schedule(self, start: int, end: int) -> int:
        self.insert_point(start)
        self.insert_point(end)
        for event in self.events.irange([start, 0], [end, 0], (True, False)):
            event[1] += 1
            self.max_overlap = max(self.max_overlap, event[1])
        return self.max_overlap

This Python implementation manages scheduling events seamlessly while tracking the maximum overlap between them using a class EventScheduler. Here's a breakdown of how the program manages the scheduling:

  • Initially, the EventScheduler class is established with an events list containing a single default event using the SortedList data structure from sortedcontainers. This setup facilitates efficient insertion and querying operations.

  • The __init__ method initializes the scheduler by setting up a baseline for tracking events in a sorted order and also sets max_overlap to zero to monitor the maximum concurrency among scheduled events.

  • insert_point is a supporting method designed to manage insertion of new points (event start or end) into the event list. It ensures points are uniquely placed in the correct sequence in the event tracking list using binary search, hence maintaining a sorted state.

  • The schedule method handles the bulk of the operation:

    • It begins by inserting the start and end points of the new event, ensuring the list order is preserved.
    • It then iterates through the range from start to end and increments the overlap count wherever applicable. During this iteration, it updates the max_overlap if the current overlap surpasses previously recorded maximum overlaps.
    • Finally, it returns the most recent value of max_overlap, which represents the highest number of simultaneous ongoing events at any point.

The primary advantage of this implementation is its efficiency across operations, primarily due to the use of SortedList. This efficiency is critical as it reduces complexity in managing and querying event overlaps, making it highly effective for scenarios with numerous and frequent schedule updates.

Comments

No comments yet.