英文原文
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 seatsn
.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 seatp
will leave the room. It is guaranteed that there will be a student sitting at seatp
.
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
- It is guaranteed that there is a student sitting at seat
p
. - At most
104
calls will be made toseat
andleave
.
中文题目
在考场里,一排有 N
个座位,分别编号为 0, 1, 2, ..., N-1
。
当学生进入考场后,他必须坐在能够使他与离他最近的人之间的距离达到最大化的座位上。如果有多个这样的座位,他会坐在编号最小的座位上。(另外,如果考场里没有人,那么学生就坐在 0 号座位上。)
返回 ExamRoom(int N)
类,它有两个公开的函数:其中,函数 ExamRoom.seat()
会返回一个 int
(整型数据),代表学生坐的位置;函数 ExamRoom.leave(int p)
代表坐在座位 p
上的学生现在离开了考场。每次调用 ExamRoom.leave(p)
时都保证有学生坐在座位 p
上。
示例:
输入:["ExamRoom","seat","seat","seat","seat","leave","seat"], [[10],[],[],[],[],[4],[]] 输出:[null,0,9,4,2,null,5] 解释: ExamRoom(10) -> null seat() -> 0,没有人在考场里,那么学生坐在 0 号座位上。 seat() -> 9,学生最后坐在 9 号座位上。 seat() -> 4,学生最后坐在 4 号座位上。 seat() -> 2,学生最后坐在 2 号座位上。 leave(4) -> null seat() -> 5,学生最后坐在 5 号座位上。
提示:
1 <= N <= 10^9
- 在所有的测试样例中
ExamRoom.seat()
和ExamRoom.leave()
最多被调用10^4
次。 - 保证在调用
ExamRoom.leave(p)
时有学生正坐在座位p
上。
通过代码
官方题解
方法一:维护有序的座位编号
我们可以用有序集合(Java
中 TreeSet
,C++
中的 set
)存储目前有学生的座位编号。当我们要调用 leave(p)
函数时,我们只需要把有序集合中的 p
移除即可。当我们要调用 seat()
函数时,我们遍历这个有序集合,对于相邻的两个座位 i
和 j
,如果选择在这两个座位之间入座,那么最近的距离 d
为 (j - i) / 2
,选择的座位为 i + d
。除此之外,我们还需要考虑坐在最左侧 0
和最右侧 N - 1
的情况。
class ExamRoom {
int N;
TreeSet<Integer> students;
public ExamRoom(int N) {
this.N = N;
students = new TreeSet();
}
public int seat() {
//Let's determine student, the position of the next
//student to sit down.
int student = 0;
if (students.size() > 0) {
//Tenatively, dist is the distance to the closest student,
//which is achieved by sitting in the position 'student'.
//We start by considering the left-most seat.
int dist = students.first();
Integer prev = null;
for (Integer s: students) {
if (prev != null) {
//For each pair of adjacent students in positions (prev, s),
//d is the distance to the closest student;
//achieved at position prev + d.
int d = (s - prev) / 2;
if (d > dist) {
dist = d;
student = prev + d;
}
}
prev = s;
}
//Considering the right-most seat.
if (N - 1 - students.last() > dist)
student = N - 1;
}
//Add the student to our sorted TreeSet of positions.
students.add(student);
return student;
}
public void leave(int p) {
students.remove(p);
}
}
class ExamRoom(object):
def __init__(self, N):
self.N = N
self.students = []
def seat(self):
# Let's determine student, the position of the next
# student to sit down.
if not self.students:
student = 0
else:
# Tenatively, dist is the distance to the closest student,
# which is achieved by sitting in the position 'student'.
# We start by considering the left-most seat.
dist, student = self.students[0], 0
for i, s in enumerate(self.students):
if i:
prev = self.students[i-1]
# For each pair of adjacent students in positions (prev, s),
# d is the distance to the closest student;
# achieved at position prev + d.
d = (s - prev) // 2
if d > dist:
dist, student = d, prev + d
# Considering the right-most seat.
d = self.N - 1 - self.students[-1]
if d > dist:
student = self.N - 1
# Add the student to our sorted list of positions.
bisect.insort(self.students, student)
return student
def leave(self, p):
self.students.remove(p)
复杂度分析
时间复杂度:
seat()
函数的时间复杂度为 $O(P)$,其中 $P$ 是当前入座学生的数目。每次调用seat()
函数我们都需要遍历整个有序集合。leave()
函数的时间复杂度为 $O(P)$(Python
代码中)或者 $O(\log P)$(Java
代码中)。空间复杂度:$O(P)$,用于存储有序集合。
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
5372 | 13141 | 40.9% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|
相似题目
题目 | 难度 |
---|---|
到最近的人的最大距离 | 中等 |