Design a system that manages the reservation state of n
seats that are numbered from 1
to n
.
Implement the SeatManager
class:
SeatManager(int n)
Initializes a SeatManager
object that will manage n
seats numbered from 1
to n
. All seats are initially available.int reserve()
Fetches the smallest-numbered unreserved seat, reserves it, and returns its number.void unreserve(int seatNumber)
Unreserves the seat with the given seatNumber
.Example 1:
Input ["SeatManager", "reserve", "reserve", "unreserve", "reserve", "reserve", "reserve", "reserve", "unreserve"] [[5], [], [], [2], [], [], [], [], [5]] Output [null, 1, 2, null, 2, 3, 4, 5, null] Explanation SeatManager seatManager = new SeatManager(5); // Initializes a SeatManager with 5 seats. seatManager.reserve(); // All seats are available, so return the lowest numbered seat, which is 1. seatManager.reserve(); // The available seats are [2,3,4,5], so return the lowest of them, which is 2. seatManager.unreserve(2); // Unreserve seat 2, so now the available seats are [2,3,4,5]. seatManager.reserve(); // The available seats are [2,3,4,5], so return the lowest of them, which is 2. seatManager.reserve(); // The available seats are [3,4,5], so return the lowest of them, which is 3. seatManager.reserve(); // The available seats are [4,5], so return the lowest of them, which is 4. seatManager.reserve(); // The only available seat is seat 5, so return 5. seatManager.unreserve(5); // Unreserve seat 5, so now the available seats are [5].
Constraints:
1 <= n <= 105
1 <= seatNumber <= n
reserve
, it is guaranteed that there will be at least one unreserved seat.unreserve
, it is guaranteed that seatNumber
will be reserved.105
calls in total will be made to reserve
and unreserve
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to managing seat reservations involves going through every single seat to find available ones. It's like checking each seat one by one when someone asks for a reservation, or to see if a seat is open. This continues until a suitable seat is found, or all seats have been checked.
Here's how the algorithm would work step-by-step:
class SeatReservationManager:
def __init__(self, number_of_seats):
self.seats = [False] * number_of_seats
def reserve(self):
# Iterate through each seat to find an available one
for seat_index in range(len(self.seats)):
#Check if current seat is available
if not self.seats[seat_index]:
self.seats[seat_index] = True
# Mark the seat as reserved and return
return seat_index
#No seat available to reserve
return None
def unreserve(self, seat_number):
#Validate seat number
if 0 <= seat_number < len(self.seats):
#Ensure that the seat has been reserved
if self.seats[seat_number]:
self.seats[seat_number] = False
We need a system to keep track of available seats in a theater and efficiently assign them to customers. The best way to do this is by using a special structure that always knows what the smallest unreserved seat number is, allowing us to assign seats quickly and keep track of what's free.
Here's how the algorithm would work step-by-step:
import heapq
class SeatReservationManager:
def __init__(self, number_of_seats):
self.available_seats = list(range(1, number_of_seats + 1))
heapq.heapify(self.available_seats)
def reserve(self):
# Always reserve the smallest available seat.
if self.available_seats:
return heapq.heappop(self.available_seats)
else:
return None
def unreserve(self, seat_number):
# Add the unreserved seat back to available seats
heapq.heappush(self.available_seats, seat_number)
Case | How to Handle |
---|---|
n is zero or negative in the constructor | Throw an IllegalArgumentException or similar to indicate invalid input; zero seats don't make sense. |
reserve() called when all seats are already reserved | The priority queue or sorted set will be empty; return an error value (e.g., -1) or throw an exception. |
unreserve() called with a seat number that is already unreserved or was never reserved | The priority queue or sorted set already contains the number; ensure no double-insertion or other undefined behavior occurs; can also be ignored if desired. |
n is a very large number, close to the maximum integer value | Ensure that the data structures used (priority queue or sorted set) can handle a large number of elements without memory issues or integer overflow. |
A sequence of reserve() and unreserve() operations leads to extreme fragmentation, meaning many small gaps of unreserved seats exist | The priority queue or sorted set handles this by maintaining the smallest available seat, though performance could degrade if very fragmented. |
Mixed calls to reserve() and unreserve() are made where reserve() retrieves an element just unreserved. | The data structure implementation must ensure consistency between reserve and unreserve so a recently unreserved seat can immediately be grabbed. |
Memory exhaustion during a large number of reserve and unreserve operations | Monitor memory usage to prevent crashes, and consider alternative data structures if memory becomes a bottleneck. |
Seat numbers close to Integer.MAX_VALUE or Integer.MIN_VALUE when unreserving | Avoid integer overflow issues when manipulating or storing seat numbers by using appropriate data types (long if needed) or carefully managing the range. |