Problem
You are implementing a program to use as your calendar. We can add a new event if adding the event will not cause a double booking.
A double booking happens when two events have some non-empty intersection (i.e., some moment is common to both events.).
The event can be represented as a pair of integers start
and end
that represents a booking on the half-open interval [start, end)
, the range of real numbers x
such that start <= x < end
.
Implement the MyCalendar
class:
MyCalendar()
Initializes the calendar object.boolean book(int start, int end)
Returnstrue
if the event can be added to the calendar successfully without causing a double booking. Otherwise, returnfalse
and do not add the event to the calendar.
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.
Solution
Method 1 - Using Treemap storing endtime as key
- TreeMap is utilised because it sorts its keys in natural ascending order for integers.
- The map’s key represents the end time, and the value corresponds to the start time.
- TreeMap is also chosen for its
higherEntry
method, which retrieves the next higher key compared to a given value (here, “start”). - For example, in TreeMap {1=One, 2=Two, 3=Three, 4=Four, 5=Five},
higherEntry(3)
returns 4=Four.
Code
Java
class MyCalendar {
private final TreeMap<Integer,Integer> calendar;
public MyCalendar() {
calendar = new TreeMap<>();
}
public boolean book(int start, int end) {
// pair where endTime in map
// is greater than provided start time
Map.Entry<Integer,Integer> higherPair = calendar.higherEntry(start);
// if pair exists and start time of pair
// is less than proided endtime
boolean isCollision = higherPair != null && end > higherPair.getValue();
if(isCollision) {
return false;
}
calendar.put(end, start);
return true;
}
}
Method 2 - Using TreeMap and start time as key
- Rather than using endTime as the key and startTime as the value, we can use startTime as the key and endTime as the value.
- Floor entry refers to the preceding event with the closest lower value.
- Ceiling entry refers to the subsequent event with the closest higher value.
Code
Java
Using Floor and ceiling entry
class MyCalendar {
final TreeMap<Integer, Integer> calendar;
public MyCalendar() {
calendar = new TreeMap<>();
}
public boolean book(int start, int end) {
// Condition for checking start time
// if current start time is lower than its lower entry end time
// that means overlapping hence return false.
if(calendar.floorEntry(start) != null && start < calendar.floorEntry(start).getValue())
return false;
// condition for checking end time
// if current end time is greater than its next event start time
// means overlapping hence return false.
if(calendar.ceilingEntry(start) != null && end > calendar.ceilingEntry(start).getKey())
return false;
calendar.put(start, end);
return true;
}
}
Using floorKey and ceilKey
class MyCalendar {
TreeMap<Integer, Integer> map;
public MyCalendar() {
map = new TreeMap<Integer, Integer> ();
}
public boolean book(int start, int end) {
Integer floorKey = map.floorKey(start);
Integer ceilKey = map.ceilingKey(start);
if (floorKey != null && start<map.get(floorKey)) {
return false;
}
if (ceilKey != null && end > ceilKey) {
return false;
}
map.put(start, end);
return true;
}
}
%%
Method 2 - Using Segment Tree
%%