Room, Booking, RecurrenceRule, and AvailabilityChecker as the core classes, efficient overlap detection for double-booking prevention, and modeling recurring meetings without materializing every future instance.
Published September 23, 2026
class Room { String id; int capacity; List<Booking> bookings; }
class Booking { String id; Room room; Instant start; Instant end; RecurrenceRule recurrence; }
interface RecurrenceRule { List<Interval> expand(Instant windowStart, Instant windowEnd); }
class AvailabilityChecker { boolean isAvailable(Room room, Instant start, Instant end); }
Separating Booking (a single reservation) from RecurrenceRule (an interface describing HOW a booking repeats) keeps the core booking model simple while letting recurrence be an independent, swappable concern — a daily standup and a one-off interview both produce Booking objects; only their recurrence behavior differs.
boolean isAvailable(Room room, Instant start, Instant end) {
// naive: O(n) scan of every existing booking
for (Booking b : room.getBookings()) {
if (start.isBefore(b.end) && b.start.isBefore(end)) return false; // classic interval overlap check
}
return true;
}
Two intervals [s1,e1) and [s2,e2) overlap exactly when s1 < e2 AND s2 < e1 — this single condition (not four separate cases) is the standard, correct overlap test, directly reusable from Merge Intervals' interval reasoning. A naive per-room linear scan is fine at small scale; at real scale, each room's bookings are better kept in a SORTED structure (a tree ordered by start time), letting a new booking request binary-search to the relevant neighborhood rather than scanning every existing booking — the same efficiency principle behind Meeting Rooms II's sorted-sweep approach, applied here to a single room's own booking list.
class WeeklyRecurrence implements RecurrenceRule {
DayOfWeek day; LocalTime time; Duration duration; Instant recurrenceEnd;
public List<Interval> expand(Instant windowStart, Instant windowEnd) {
// computes only the occurrences WITHIN the requested window, on demand
}
}
A naive implementation might insert a separate Booking row for every future occurrence of a recurring meeting the moment it's created ("every Monday for the next 2 years" → hundreds of rows immediately) — this wastes storage for occurrences that may never happen (the series could be cancelled next month) and makes editing the WHOLE series afterward require updating every materialized row. The better approach stores the recurrence RULE once, and expand() computes concrete occurrences ON DEMAND, only for whatever window is actually being queried (e.g. "show me next week's bookings") — this is the same lazy-computation principle behind not pre-computing data you might never need.
Q: How do you handle editing a single occurrence of a recurring series ("just this Tuesday's meeting is moved"), given occurrences aren't materialized?
A: A common pattern adds an explicit EXCEPTION list to the recurrence rule (specific dates that deviate from the base rule, either cancelled or moved) — expand() then applies the base rule and overlays exceptions, rather than forcing a full materialize-then-edit model just to support the single-occurrence-edit case.
Q: Does the overlap check need to account for time zones?
A: Yes, critically — comparing Instant values (an absolute point in time, not a wall-clock time) sidesteps time zone ambiguity entirely for the overlap CHECK itself; time zones only matter for DISPLAYING the booking to a user in their local time, a presentation-layer concern kept separate from the core availability logic.
Q: How would you scale availability checking across thousands of rooms simultaneously (e.g. 'find any available room for 2pm')? A: This shifts from a per-room overlap check to a genuine search problem — indexing rooms by capacity/location and maintaining each room's near-term booked intervals in a fast-queryable structure lets a 'find available' query filter candidates efficiently, rather than checking every room's full booking list linearly for every search.
Q: How does this design relate to Meeting Rooms II, the DSA problem? A: Meeting Rooms II answers a narrower analytical question — given a fixed list of intervals, what's the PEAK concurrent count — using the same sort-and-sweep technique that a real booking system's capacity-planning or reporting feature would reuse; the LLD system here is the broader, stateful, ongoing service that a query like Meeting Rooms II might run AGAINST, not a replacement for it.