加载中...
855-考场就座(Exam Room)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.4k | 阅读时长: 7分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/exam-room

英文原文

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
  • It is guaranteed that there is a student sitting at seat p.
  • At most 104 calls will be made to seat and leave.

中文题目

在考场里,一排有 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. 1 <= N <= 10^9
  2. 在所有的测试样例中 ExamRoom.seat() 和 ExamRoom.leave() 最多被调用 10^4 次。
  3. 保证在调用 ExamRoom.leave(p) 时有学生正坐在座位 p 上。

通过代码

官方题解

方法一:维护有序的座位编号

我们可以用有序集合(JavaTreeSetC++ 中的 set)存储目前有学生的座位编号。当我们要调用 leave(p) 函数时,我们只需要把有序集合中的 p 移除即可。当我们要调用 seat() 函数时,我们遍历这个有序集合,对于相邻的两个座位 ij,如果选择在这两个座位之间入座,那么最近的距离 d(j - i) / 2,选择的座位为 i + d。除此之外,我们还需要考虑坐在最左侧 0 和最右侧 N - 1 的情况。

[sol1]
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); } }
[sol1]
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%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
到最近的人的最大距离 中等
上一篇:
854-相似度为 K 的字符串(K-Similar Strings)
下一篇:
856-括号的分数(Score of Parentheses)
本文目录
本文目录