My Calendar I

Updated on 19 June, 2025
My Calendar I header image

Problem Statement

In the given scenario, you are tasked with developing a calendar program capable of managing events. The primary constraint is to ensure there are no double bookings, meaning no two events should overlap even partially. Events are defined by a starting time (startTime) and an ending time (endTime), encapsulating all moments x such that startTime <= x < endTime. You must implement a MyCalendar class with two functionalities:

  • MyCalendar(): a constructor that initializes the calendar.
  • boolean book(int startTime, int endTime): a method that checks if the event can be added to the calendar without causing a double booking. It returns true if the event can be added without overlap, else it returns false.

This functionality should handle time complexities and manage the overlapping of events efficiently given the constraints.

Examples

Example 1

Input:

["MyCalendar", "book", "book", "book"]
[[], [10, 20], [15, 25], [20, 30]]

Output:

[null, true, false, true]

Explanation:

MyCalendar myCalendar = new MyCalendar();
myCalendar.book(10, 20); // return True
myCalendar.book(15, 25); // return False, It can not be booked because time 15 is already booked by another event.
myCalendar.book(20, 30); // return True, The event can be booked, as the first event takes every time less than 20, but not including 20.

Constraints

  • 0 <= start < end <= 10⁹
  • At most 1000 calls will be made to book.

Approach and Intuition

To ensure that new bookings do not overlap with existing events, we can use a straightforward approach:

  1. Data Structure: Maintain a list (or array) of booked time intervals.

  2. Booking Logic (book(start, end)):

    • Iterate over each existing event in the list.

    • For every event (s, e) in the list, check for overlap using the condition:

      • start < e && end > s
      • This checks if the new event starts before the current event ends and ends after the current event starts.
    • If any overlap is found, return false.

    • If no overlaps exist, append the new event to the list and return true.

  3. Efficiency:

    • Since the number of operations is limited to 1000 calls, the worst-case time complexity of O(N) per call (where N is the number of events) is acceptable.
    • For larger input sizes, one might consider segment trees, balanced BSTs, or other interval management data structures to optimize performance.

This method ensures correct behavior under all valid inputs and is backed by a simple yet effective overlap detection mechanism.

Solutions

  • C++
  • Java
  • Python
cpp
class Scheduler {
private:
    set<pair<int, int>> bookings;

public:
    bool reserve(int startTime, int endTime) {
        pair<int, int> newEvent{startTime, endTime};
        auto it = bookings.lower_bound(newEvent);
        if (it != bookings.end() && it->first < endTime) {
            return false;
        }
        
        if (it != bookings.begin()) {
            auto previousEvent = prev(it);
            if (previousEvent->second > startTime) {
                return false;
            }
        }

        bookings.insert(newEvent);
        return true;
    }
};

This C++ solution defines a class Scheduler that facilitates the booking of events without any overlap in their scheduled times. The main functionality is encapsulated within the reserve method, which verifies and allows the addition of new events to a set of booked time intervals.

  • The bookings set holds pairs of integers, each pair representing the start and end time of an event. This set automatically keeps the entries sorted by their start times.
  • The reserve method checks if there is any overlap with other existing bookings before inserting a new entry:
    1. Construct a pair newEvent from the provided startTime and endTime.
    2. Search for potential conflicts using lower_bound to determine where the newEvent would fit within the set based on the start time.
    3. Check against the next pre-existing event found by lower_bound to ensure the new event's end time does not overlap with this event's start time.
    4. Also check the event just before the insertion point (if it exists) to see if its end time overlaps with the start of the new event.
    5. If no overlaps are found, insert the new event into the set.
    6. Return true if the event is successfully booked, and false if the event conflicts with existing bookings.

This solution effectively handles booking queries with time complexity driven largely by set operations, specifically insert and lower_bound, both operating at logarithmic time complexity relative to the number of elements.

java
class EventScheduler {
    TreeMap<Integer, Integer> events;

    EventScheduler() {
        events = new TreeMap<>();
    }

    public boolean schedule(int start, int end) {
        Integer previous = events.floorKey(start),
                upcoming = events.ceilingKey(start);
        if ((previous == null || events.get(previous) <= start) &&
                (upcoming == null || end <= upcoming)) {
            events.put(start, end);
            return true;
        }
        return false;
    }
}

The "My Calendar I" implementation involves creating a scheduling system where non-overlapping events can be added, and implemented in Java using a TreeMap. Below is a breakdown of the provided solution:

  • Define the EventScheduler class with a private TreeMap named events to manage the events. The keys of this map are the start times of events, and the values are their corresponding end times.

  • The constructor EventScheduler() initializes the events TreeMap.

  • Implement the schedule() method to add new events:

    1. Use TreeMap.floorKey() to locate the largest key less than or equal to the current start time.
    2. Use TreeMap.ceilingKey() to find the smallest key greater than or equal to the start time.
    3. Check for overlaps:
    • Ensure the event ending before the current start time either does not exist or finishes before the new event starts.
    • Make sure there is no existing event starting before the current event ends.
    1. If no overlap occurs, insert the new event into the events map with the start time as the key and the end time as the value, then return true.
    2. If an overlap is detected, return false to indicate the event cannot be scheduled.

This solution efficiently checks for event overlap and maintains ordered events ensuring that any scheduling or querying operations are handled optimally.

python
from sortedcontainers import SortedList

class Scheduler:
    def __init__(self):
        self.appointments = SortedList()

    def make_booking(self, start_time: int, end_time: int) -> bool:
        position = self.appointments.bisect_right((start_time, end_time))
        if (position > 0 and self.appointments[position-1][1] > start_time) or (position < len(self.appointments) and self.appointments[position][0] < end_time):
            return False
        self.appointments.add((start_time, end_time))
        return True

The problem "My Calendar I" involves building a scheduler that manages time-based appointments without overlapping. The solution is implemented in Python 3 using the SortedList from the sortedcontainers module which ensures automatic sorting and offers fast insertion times.

Here's how the provided solution operates:

  • Initially, define a Scheduler class with an appointments attribute, a SortedList that holds confirmed appointments as tuples of (start_time, end_time).

  • The make_booking method handles the booking process:

    • Calculate the insertion position using bisect_right to find the appropriate spot in the sorted list for the new appointment.
    • Check existing appointments around this position to prevent overlaps:
      • If there's an appointment before the current spot that ends after the new appointment begins, reject the booking.
      • If there's an appointment after the current spot that starts before the new appointment ends, reject the booking.
    • If no overlaps are found, add the new appointment to the list using .add(), and confirm the booking by returning True.

This implementation efficiently manages appointments by leveraging the sorted nature of SortedList, achieving fast query and insertion times, crucial for applications dealing with large datasets or requiring prompt responses.

Comments

No comments yet.