import bisect
class ExamRoom:
def __init__(self, N):
self.N = N
# 记录学生的位置
self.students = []
def seat(self):
# 还没有学生,直接坐在第一个位置
if not self.students:
student = 0
else:
# 有学生,要比较相邻学生之间的位置
dist, student = self.students[0], 0
for i, s in enumerate(self.students):
if i:
prev = self.students[i - 1]
# 与前一个学生之间的中间的位置
d = int((s - prev) / 2)
# 记录最大的间隔,以及插入的位置
if d > dist:
dist, student = d, prev + d
# 最后一个学生与最后一个位置的距离
d = self.N - 1 - self.students[-1]
if d > dist:
student = self.N - 1
# 按顺序插入学生的位置
bisect.insort(self.students, student)
return student
def leave(self, p):
self.students.remove(p)
N = 10
obj = ExamRoom(N)
print(obj.students)
obj.seat()
print(obj.students)
obj.seat()
print(obj.students)
obj.seat()
print(obj.students)
obj.leave(0)
print(obj.students)
obj.seat()
print(obj.students)
obj.leave(4)
print(obj.students)
obj.seat()
print(obj.students)
obj.leave(9)
print(obj.students)
obj.seat()
print(obj.students)
obj.seat()
print(obj.students)
# 输出
[]
[0]
[0, 9]
[0, 4, 9]
[4, 9]
[0, 4, 9]
[0, 9]
[0, 4, 9]
[0, 4]
[0, 4, 9]
[0, 2, 4, 9]
列表中元素需要按照顺序排好序,插入元素有序插入,需要用到bisect库函数;首先初始化列表为空,初始化数量N,列表中存放的是索引位置,所以长度不一定等于N;对于seat函数,遍历可能插入的位置,也就是列表中每个元素的前一个位置和这个位置的中间,如果在遍历中找到大于上一个间隔的则更新距离和插入的值:
if d > dist:
dist, student = d, prev + d
记得每次存放上一个位置的值;另外要考虑第一个和最后一个位置的特殊情况,因为如果列表中最后一个元素不是N-1,是4的话,遍历插入的位置只会考虑4之前的,所以每次要计算下最后一个位置的元素离N-1有多远,如果大于之前保存的最大dist,那么就要更新student为最后一个值N-1了;每次for循环的 for i, s in enumerate(self.students):
中的第一个都是等于0,因为前面没有元素所以不考虑这个,但是要保存0位置离它最远的,可能0位置没有坐学生,但是距离是最大的,dist, student = self.students[0], 0
,这里后面如果会找大更大的,会自动更新,没找到那么就是它了,符合距离最大,距离相等取最小的。