There is an exam room with n
seats in a single row labeled from 0
to n - 1
.
When a student enters the room, they must sit in the seat that maximizes the distance to the closest person. If there are multiple such seats, they sit in the seat with the lowest number. If no one is in the room, then the student sits at seat number 0
.
Design a class that simulates the mentioned exam room.
Implement the ExamRoom
class:
ExamRoom(int n)
Initializes the object of the exam room with the number of the seats n
.int seat()
Returns the label of the seat at which the next student will set.void leave(int p)
Indicates that the student sitting at seat p
will leave the room. It is guaranteed that there will be a student sitting at seat p
.Example 1:
Input ["ExamRoom", "seat", "seat", "seat", "seat", "leave", "seat"] [[10], [], [], [], [], [4], []] Output [null, 0, 9, 4, 2, null, 5] Explanation ExamRoom examRoom = new ExamRoom(10); examRoom.seat(); // return 0, no one is in the room, then the student sits at seat number 0. examRoom.seat(); // return 9, the student sits at the last seat number 9. examRoom.seat(); // return 4, the student sits at the last seat number 4. examRoom.seat(); // return 2, the student sits at the last seat number 2. examRoom.leave(4); examRoom.seat(); // return 5, the student sits at the last seat number 5.
Constraints:
1 <= n <= 109
p
.104
calls will be made to seat
and leave
.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 exam room problem is about figuring out the best seat to assign. A brute force approach means we'll check every single seat one by one to see which is the best.
Here's how the algorithm would work step-by-step:
class ExamRoom:
def __init__(self, room_size):
self.room_size = room_size
self.students = []
def seat(self):
if not self.students:
self.students.append(0)
return 0
# Consider sitting at the beginning.
max_distance = self.students[0]
seat_position = 0
# Check the distances between occupied seats.
for i in range(1, len(self.students)):
distance = (self.students[i] - self.students[i - 1]) // 2
if distance > max_distance:
# Because current distance is the largest
max_distance = distance
seat_position = self.students[i - 1] + distance
# Consider sitting at the end.
if self.room_size - 1 - self.students[-1] > max_distance:
seat_position = self.room_size - 1
# Find the correct position to insert
insert_index = 0
while insert_index < len(self.students) and self.students[insert_index] < seat_position:
insert_index += 1
# Insert the student into the sorted list
self.students.insert(insert_index, seat_position)
return seat_position
def leave(self, student_position):
self.students.remove(student_position)
The problem can be solved efficiently by focusing on maintaining the largest possible distance between students. We use a system that keeps track of occupied seats and then quickly identifies where to place the next student to maximize that distance.
Here's how the algorithm would work step-by-step:
class ExamRoom:
def __init__(self, room_size):
self.room_size = room_size
self.occupied_seats = []
def seat(self):
if not self.occupied_seats:
self.occupied_seats.append(0)
return 0
max_distance = self.occupied_seats[0]
seat_position = 0
#Find the maximum distance between occupied seats.
for i in range(1, len(self.occupied_seats)):
distance = (self.occupied_seats[i] - self.occupied_seats[i - 1]) // 2
if distance > max_distance:
max_distance = distance
seat_position = self.occupied_seats[i - 1] + distance
#Check the distance to the end of the room.
if self.room_size - 1 - self.occupied_seats[-1] > max_distance:
max_distance = self.room_size - 1 - self.occupied_seats[-1]
seat_position = self.room_size - 1
self.occupied_seats.append(seat_position)
self.occupied_seats.sort()
return seat_position
def leave(self, seat_number):
#Remove student from occupied seats when they leave.
self.occupied_seats.remove(seat_number)
Case | How to Handle |
---|---|
Initial exam room is empty (n=0) | Throw an exception or return an appropriate error code since an exam room must have a positive size. |
Calling seat() when the room is full (all seats are occupied) | Return -1 to indicate no seat available or throw an exception if the API does not allow such action. |
Calling leave(p) with an invalid seat number (p not seated) | Ignore the request, throw an exception or return an error code indicating the seat is not occupied. |
Very large n (room size) impacting memory usage or performance of calculations | Use efficient data structures such as a balanced binary search tree or a priority queue to manage seated positions, reducing the time complexity of seat() and leave(). |
Floating-point calculations for distance between seats, potentially leading to precision errors | Avoid floating-point operations or use integers whenever possible, and if needed, use an epsilon value for comparisons to account for potential inaccuracies. |
The same person tries to 'leave' multiple times | Ensure that after a person leaves, their ID is removed from any data structures storing seated people, preventing double removal issues. |
leave(p) with p being a negative or zero value. | Throw IllegalArgumentException if p is a zero or negative number. |
n (room size) is negative. | Throw IllegalArgumentException if n is a negative number. |