Design Bus Seat Booking System - Solution & Explanation
Problem Statement
You are asked to design a seat booking system for a bus.
The bus has n rows. Each row has four seats labeled "A", "B", "C", and "D".
Seats "A" and "D" are window seats; seats "B" and "C" are middle seats. In each row, seat "A" is adjacent to seat "B", and seat "D" is adjacent to seat "C".
Booking rules:
- Booking a middle seat (
"B"or"C") always takes 1 second. - Booking a window seat (
"A"or"D") takes 1 second if its adjacent middle seat is not booked, or 3 seconds (an extra delay of 2 seconds) if its adjacent middle seat is already booked.
A seat is identified by a string such as "A1" or "D20" (one letter from A to D followed by its row number).
Implement the BusBooking class:
BusBooking(int n): Initializes the system withnempty rows.void toggle(string seat): Booksseatif it is free, or frees it if it is already booked.int getTotalTime(): Returns the total time (in seconds) taken to book all currently booked seats, where the seats are booked in the order theirtogglecalls were made. If no seats are currently booked, return 0.int getMinTime(): Returns the smallest possible total time (in seconds) to book all currently booked seats, over every possible order of booking them. If no seats are currently booked, return 0.
Note: The time cost of a seat is fixed at the moment it is booked, based on the seats booked at that time. Booking or freeing other seats afterward does not change the cost of a seat that is already booked.
Example 1:
Input:
["BusBooking", "toggle", "toggle", "getTotalTime", "getMinTime", "toggle", "toggle", "getTotalTime", "getMinTime"]
[[20], ["B3"], ["A3"], [], [], ["C3"], ["D3"], [], []]
Output:
[null, null, null, 4, 2, null, null, 8, 4]
Explanation
BusBooking busBooking = new BusBooking(20); // start with 20 empty rowsbusBooking.toggle("B3"); // book
"B3", a middle seat, which costs 1 second. Total time is now 1.busBooking.toggle("A3"); // book
"A3", a window seat. Its adjacent middle "B3" is already booked, so it costs 3 seconds. Total time is now 1 + 3 = 4.busBooking.getTotalTime(); // return 4, since in toggle order
"B3" costs 1 and "A3" costs 3.busBooking.getMinTime(); // return 2. Booking
"A3" before "B3" avoids the delay, so 2 seats takes 2 second to book.busBooking.toggle("C3"); // book
"C3", a middle seat, which costs 1 second. Total time is now 1 + 4 = 5.busBooking.toggle("D3"); // book
"D3", a window seat. Its adjacent middle "C3" is already booked, so it costs 3 seconds. Total time is now 5 + 3 = 8.busBooking.getTotalTime(); // return 8, since in toggle order the seat costs are 1, 3, 1, 3.
busBooking.getMinTime(); // return 4. With the best possible booking order, no delay is added, so the 4 booked seats take
4 * 1 = 4 seconds.Example 2:
Input:
["BusBooking", "toggle", "toggle", "getTotalTime", "toggle", "toggle", "toggle", "getTotalTime", "getMinTime"]
[[10], ["C7"], ["D7"], [], ["D7"], ["C7"], ["D7"], [], []]
Output:
[null, null, null, 4, null, null, null, 1, 1]
Explanation
BusBooking busBooking = new BusBooking(10); // start with 10 empty rowsbusBooking.toggle("C7"); // book
"C7", a middle seat, which costs 1 second. Total time is now 1.busBooking.toggle("D7"); // book
"D7", a window seat. Its adjacent middle "C7" is already booked, so it costs 3 seconds. Total time is now 1 + 3 = 4.busBooking.getTotalTime(); // return 4, since in toggle order
"C7" costs 1 and "D7" costs 3.busBooking.toggle("D7"); //
"D7" is already booked, so free it. This removes its cost of 3. Total time is now 4 - 3 = 1.busBooking.toggle("C7"); //
"C7" is already booked, so free it. This removes its cost of 1. Total time is now 1 - 1 = 0, and row 7 is empty.busBooking.toggle("D7"); // book
"D7" again, a window seat. Its adjacent middle "C7" is not booked this time, so it costs only 1 second. Total time is now 0 + 1 = 1.busBooking.getTotalTime(); // return 1, since only
"D7" is booked and it cost 1 this time.busBooking.getMinTime(); // return 1. With the best possible booking order, the 1 booked seat takes
1 * 1 = 1 second.
Constraints:
1 <= n <= 105āāāāāāāseat[0]is one of'A','B','C','D'.- The remaining characters of
seatform an integerrowwith1 <= row <= n. - The total number of calls to
toggle,getTotalTime, andgetMinTimedoes not exceed105.
Approach Overview
Problem Overview: You manage a bus with numbered seats. Reserving returns the smallest-numbered free seat and marks it taken. Cancelling a specific seat makes it free again. Every operation has to be fast, and the reserve operation always has to find the smallest free seat.
Approach 1: Linear Scan over a Boolean Array (O(n) per reserve, O(n) space)
Keep a boolean array where index i tells you whether seat i is booked. On reserve, iterate from seat 1 upward and return the first index that is free. Cancel is a single write to the array, so it runs in O(1). This is simple and correct, but reserve gets slow when most seats are booked, because you scan the same prefix over and over. Use it only as a baseline to explain the bottleneck.
Approach 2: Min-Heap with Lazy Deletion (O(log n) per operation, O(n) space)
Store all free seats in a min-heap. Reserve calls heappop to get the smallest free seat in O(log n). Cancel pushes the seat back into the heap in O(log n). To prevent duplicates, keep a hash set of currently free seats so you can reject a cancel for a seat that is already free. The key insight is that the heap gives you the minimum for free, so you never scan. Prefer this approach when the number of seats is large and reserve is the dominant call.
Approach 3: Ordered Set or Segment Tree (O(log n) per operation, O(n) space)
A balanced BST or a segment tree over seat indices also gives O(log n) for both operations. The segment tree stores the count of free seats in each range, so reserve descends toward the leftmost leaf with a free seat. This avoids duplicate handling and works well if you later add range queries, such as counting free seats between two numbers. It takes more code than the heap, so reach for it only when you need those extra queries.
Recommended for interviews: Start with the linear scan to show you understand the state. Then move to the min-heap with a hash set. The brute force shows you can model the problem. The heap solution shows you can pick the right data structure for the operation that matters most. Mention the segment tree as an alternative if the interviewer asks for range queries. Review the heap topic and design topic if the lazy deletion pattern is new to you.
Solution
Thinking
Both the number of rows and the number of calls can reach
10^5, so replaying the whole booking history on every query exceeds the limit.A window seat costs an extra
2seconds only when its adjacent middle seat is already booked, and that cost is fixed at the momenttogglebooks it.getTotalTimeis the sum of the costs recorded for the seats that are still occupied.
getMinTimemay reorder the booking of those seats. A middle seat always costs1second; booking a window seat before its adjacent middle seat avoids the extra2seconds. The minimum time is therefore the number of seats currently booked. Store each seat's cost from the moment it was booked, keep the total and the occupancy count separately, and every operation isO(1).
Each row is stored as an array of length 4. A cell value of 0 means the seat is free; otherwise it is the number of seconds fixed when that seat was booked. The variable tot keeps the sum of these costs, and a counter keeps the number of seats currently booked.
When toggle sees a booked seat, subtract its stored cost from tot, decrease the counter, and clear the cell. When the seat is free, a middle seat \texttt{B} or \texttt{C} costs 1 second. A window seat \texttt{A} or \texttt{D} costs 3 seconds if its adjacent middle seat is already booked, and 1 second otherwise. Write that cost into the array and update both tot and the counter.
getTotalTime returns tot, and getMinTime returns the number of booked seats.
Each operation takes O(1) time, and the space complexity is O(n), where n is the number of rows.
Code
Python
Java
C++
Go
TypeScript
Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Linear scan over boolean array | Reserve O(n), Cancel O(1) | O(n) | Small bus, or as a baseline before optimizing |
| Min-heap with hash set | Reserve O(log n), Cancel O(log n) | O(n) | General case, frequent reserve calls |
| Segment tree or ordered set | O(log n) per operation | O(n) | When you also need range queries over free seats |
Video Solutions (4)
LeetCode | Weekly Contest 523 Q3 | Design Bus Seat Booking System | C++
Frequently Asked Questions
Design Bus Seat Booking System Python solution?
Is Design Bus Seat Booking System easy or hard?
How to solve Design Bus Seat Booking System in O(log n)?
What is the best approach for Design Bus Seat Booking System?
What data structure is used in Design Bus Seat Booking System?
What is the time complexity of Design Bus Seat Booking System?
Is Design Bus Seat Booking System asked at Google, Amazon, or Meta?
Ready to solve this problem?
Practice Design Bus Seat Booking System with our built-in code editor and test cases.
Practice on FleetCodeProblem Info
Table of Contents
Practice this problem
Open in Editor