855. 考场就座

在这里插入图片描述

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,这里后面如果会找大更大的,会自动更新,没找到那么就是它了,符合距离最大,距离相等取最小的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值