我的解法:
1.考虑极端情况,无人就座,只有1人就座且(坐在左边,中间,最右边),只剩下最左边和最右边的座位等等
2.想的是查找最大的间隔,如果间隔两端都有人那么就坐中间,如果间隔左边没人坐左边,左边有人右边无人坐右边
3.如果间隔大于1/2总长度就可以跳出了,后面的间隔不会更大了
class ExamRoom:
def __init__(self, n: int):
self.seat_list=[]
self.seat_set=set()
self.left=0
self.right=0
self.n=n
def seat(self) -> int:
n=self.n
if self.seat_list==[]:
self.seat_list.append(0)
self.seat_set.add(0)
return 0
if len(self.seat_set)>=n-2 and 0 not in self.seat_set:
self.seat_list.insert(0,0)
self.seat_set.add(0)
return 0
last=-1
max_gap=n-1-self.seat_list[-1]-1
if max_gap<0:
max_gap=0
left=-1
right=n
half_gap=n//2
insert_loc=0
for student in range(0,len(self.seat_list)):
gap=self.seat_list[student]-last
if gap//2>max_gap//2:
max_gap=gap
left=last
right=self.seat_list[student]
insert_loc=student
if max_gap>half_gap:
break
last=self.seat_list[student]
if left in self.seat_set and right in self.seat_set:
new_seat=(left+right)//2
self.seat_list.insert(insert_loc,new_seat)
self.seat_set.add(new_seat)
return new_seat
if n-1 not in self.seat_set:
self.seat_list.append(n-1)
self.seat_set.add(n-1)
return n-1
self.seat_list.insert(0,0)
self.seat_set.add(0)
return 0
def leave(self, p: int) -> None:
self.seat_list.remove(p)
self.seat_set.remove(p)
标准解法:
class ExamRoom:
def __init__(self, n: int):
self.heap_info = []
self.last = n - 1
heappush(self.heap_info, [-self.last, -1, self.last + 1])
def seat(self) -> int:
gap, left, right = heappop(self.heap_info)
if left < 0:
if right > self.last:
heappush(self.heap_info, [-self.last, 0, right])
elif right > 1:
heappush(self.heap_info, [-(right >> 1), 0, right])
return 0
elif right > self.last:
if gap < -1:
heappush(self.heap_info, [-(-gap >> 1), left, self.last])
return self.last
else:
seat_idx = left - gap
if gap < -1:
heappush(self.heap_info, [-(-gap >> 1), left, seat_idx])
heappush(self.heap_info, [-((right - seat_idx) >> 1), seat_idx, right])
elif left + 3 == right:
heappush(self.heap_info, [-1, seat_idx, right])
return seat_idx
def leave(self, p: int) -> None:
if p == 0:
right = 1
for i in range(len(self.heap_info)):
if self.heap_info[i][1] == 0:
_, _, right = self.heap_info.pop(i)
break
heappush(self.heap_info, [-right, -1, right])
elif p == self.last:
left = p - 1
for i in range(len(self.heap_info)):
if self.heap_info[i][2] == self.last:
_, left, _ = self.heap_info.pop(i)
break
heappush(self.heap_info, [left - self.last, left, self.last + 1])
else:
cnt = 0
left, right = p - 1, p + 1
for i in range(len(self.heap_info) - 1, -1, -1):
if self.heap_info[i][1] == p:
_, _, right = self.heap_info.pop(i)
if cnt == 1:
break
cnt = 1
elif self.heap_info[i][2] == p:
_, left, _ = self.heap_info.pop(i)
if cnt == 1:
break
cnt = 1
if left < 0:
gap = right
elif right > self.last:
gap = self.last - left
else:
gap = (right - left) >> 1
heappush(self.heap_info, [-gap, left, right])
return None
python的heappush和heappop:
1.heappush(heap,item)建立大、小根堆
heapq.heappush()是往堆中添加新值,此时自动建立了小根堆
不能直接建立大跟堆,所以每次push时给元素加一个负号(即取相反数),此时最小值变最大值,反之亦然,那么实际上的最大值就可以处于堆顶了,返回时再取负即可。
2.heapq.heappop()从堆中弹出并返回最小的值
普通list(即并没有进行heapify等操作的list),对他进行heappop操作并不会弹出list中最小的值,而是弹出第一个值。
对于小跟堆,会依次弹出最小的值。
x>>1相当于快速的x//2
原文链接:https://blog.csdn.net/qq_38022469/article/details/123851001
其他解答:
区间的左右两边用有序列表存储,元素是一个元组,排序的key是计算距离的负数,这样可以确保大的值排在前面,第二个排序依据是x[0]就是区间的左边位置,确保先坐序号小的
这样seat的时候就相当于删除了原来的区间,把其分割为两个新的区间。
两个字典存放的是当前学生左右两边的学生,方便删除的时候合并区间,这个比较好懂一些
from sortedcontainers import SortedList
class ExamRoom:
def __init__(self, n: int):
def dist(x):
l, r = x
return r - l - 1 if l == -1 or r == n else (r - l) >> 1
self.n = n
self.ts = SortedList(key=lambda x: (-dist(x), x[0]))
self.left = {}
self.right = {}
self.add((-1, n))
def seat(self) -> int:
s = self.ts[0]
p = (s[0] + s[1]) >> 1
if s[0] == -1:
p = 0
elif s[1] == self.n:
p = self.n - 1
self.delete(s)
self.add((s[0], p))
self.add((p, s[1]))
return p
def leave(self, p: int) -> None:
l, r = self.left[p], self.right[p]
self.delete((l, p))
self.delete((p, r))
self.add((l, r))
def add(self, s):
self.ts.add(s)
self.left[s[1]] = s[0]
self.right[s[0]] = s[1]
def delete(self, s):
self.ts.remove(s)
self.left.pop(s[1])
self.right.pop(s[0])
作者:lcbin
链接:https://leetcode.cn/problems/exam-room/solution/by-lcbin-tstp/
来源:力扣(LeetCode)