Skip to content

Commit 30fef90

Browse files
committed
feat: add solutions to lc problem: No.0855
No.0855.Exam Room
1 parent 7a22e31 commit 30fef90

File tree

6 files changed

+757
-0
lines changed

6 files changed

+757
-0
lines changed

solution/0800-0899/0855.Exam Room/README.md

+262
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,284 @@ seat() -> 5,学生最后坐在 5 号座位上。
4242

4343
<!-- 这里可写通用的实现逻辑 -->
4444

45+
**方法一:有序集合 + 哈希表**
46+
47+
考虑到每次 `seat` 都需要找到最大距离的座位,因此我们可以使用有序集合来维护所有座位之间的距离,距离越大的座位会越先被选中。
48+
49+
有序集合的每个元素为一个二元组 $(l, r)$,表示 $l$ 和 $r$ 之间(不包括 $l$ 和 $r$)的座位可以坐人,初始时有序集合中只有一个元素 $(-1, n)$,表示 $(-1, n)$ 之间的座位可以坐人。
50+
51+
另外,我们使用两个哈希表 `left``right` 来维护每个位置左右两侧坐着人的位置,方便我们在 `leave` 时合并两个空闲的座位区间。
52+
53+
时间复杂度 $O(\log n)$,空间复杂度 $O(n)$。其中 $n$ 为考场的座位数。
54+
4555
<!-- tabs:start -->
4656

4757
### **Python3**
4858

4959
<!-- 这里可写当前语言的特殊实现逻辑 -->
5060

5161
```python
62+
from sortedcontainers import SortedList
63+
64+
65+
class ExamRoom:
66+
67+
def __init__(self, n: int):
68+
def dist(x):
69+
l, r = x
70+
return r - l - 1 if l == -1 or r == n else (r - l) >> 1
71+
72+
self.n = n
73+
self.ts = SortedList(key=lambda x: (-dist(x), x[0]))
74+
self.left = {}
75+
self.right = {}
76+
self.add((-1, n))
77+
78+
def seat(self) -> int:
79+
s = self.ts[0]
80+
p = (s[0] + s[1]) >> 1
81+
if s[0] == -1:
82+
p = 0
83+
elif s[1] == self.n:
84+
p = self.n - 1
85+
self.delete(s)
86+
self.add((s[0], p))
87+
self.add((p, s[1]))
88+
return p
89+
90+
def leave(self, p: int) -> None:
91+
l, r = self.left[p], self.right[p]
92+
self.delete((l, p))
93+
self.delete((p, r))
94+
self.add((l, r))
5295

96+
def add(self, s):
97+
self.ts.add(s)
98+
self.left[s[1]] = s[0]
99+
self.right[s[0]] = s[1]
100+
101+
def delete(self, s):
102+
self.ts.remove(s)
103+
self.left.pop(s[1])
104+
self.right.pop(s[0])
105+
106+
107+
# Your ExamRoom object will be instantiated and called as such:
108+
# obj = ExamRoom(n)
109+
# param_1 = obj.seat()
110+
# obj.leave(p)
53111
```
54112

55113
### **Java**
56114

57115
<!-- 这里可写当前语言的特殊实现逻辑 -->
58116

59117
```java
118+
class ExamRoom {
119+
private TreeSet<int[]> ts = new TreeSet<>((a, b) -> {
120+
int d1 = dist(a), d2 = dist(b);
121+
return d1 == d2 ? a[0] - b[0] : d2 - d1;
122+
});
123+
private Map<Integer, Integer> left = new HashMap<>();
124+
private Map<Integer, Integer> right = new HashMap<>();
125+
private int n;
126+
127+
public ExamRoom(int n) {
128+
this.n = n;
129+
add(new int[] {-1, n});
130+
}
131+
132+
public int seat() {
133+
int[] s = ts.first();
134+
int p = (s[0] + s[1]) >> 1;
135+
if (s[0] == -1) {
136+
p = 0;
137+
} else if (s[1] == n) {
138+
p = n - 1;
139+
}
140+
del(s);
141+
add(new int[] {s[0], p});
142+
add(new int[] {p, s[1]});
143+
return p;
144+
}
145+
146+
public void leave(int p) {
147+
int l = left.get(p), r = right.get(p);
148+
del(new int[] {l, p});
149+
del(new int[] {p, r});
150+
add(new int[] {l, r});
151+
}
152+
153+
private int dist(int[] s) {
154+
int l = s[0], r = s[1];
155+
return l == -1 || r == n ? r - l - 1 : (r - l) >> 1;
156+
}
157+
158+
private void add(int[] s) {
159+
ts.add(s);
160+
left.put(s[1], s[0]);
161+
right.put(s[0], s[1]);
162+
}
163+
164+
private void del(int[] s) {
165+
ts.remove(s);
166+
left.remove(s[1]);
167+
right.remove(s[0]);
168+
}
169+
}
170+
171+
/**
172+
* Your ExamRoom object will be instantiated and called as such:
173+
* ExamRoom obj = new ExamRoom(n);
174+
* int param_1 = obj.seat();
175+
* obj.leave(p);
176+
*/
177+
```
178+
179+
### **C++**
180+
181+
```cpp
182+
int N;
183+
184+
int dist(const pair<int, int>& p) {
185+
auto [l, r] = p;
186+
if (l == -1 || r == N) return r - l - 1;
187+
return (r - l) >> 1;
188+
}
189+
190+
struct cmp {
191+
bool operator()(const pair<int, int>& a, const pair<int, int>& b) const {
192+
int d1 = dist(a), d2 = dist(b);
193+
return d1 == d2 ? a.first < b.first : d1 > d2;
194+
};
195+
};
196+
197+
class ExamRoom {
198+
public:
199+
ExamRoom(int n) {
200+
N = n;
201+
this->n = n;
202+
add({-1, n});
203+
}
204+
205+
int seat() {
206+
auto s = *ts.begin();
207+
int p = (s.first + s.second) >> 1;
208+
if (s.first == -1) {
209+
p = 0;
210+
} else if (s.second == n) {
211+
p = n - 1;
212+
}
213+
del(s);
214+
add({s.first, p});
215+
add({p, s.second});
216+
return p;
217+
}
218+
219+
void leave(int p) {
220+
int l = left[p], r = right[p];
221+
del({l, p});
222+
del({p, r});
223+
add({l, r});
224+
}
225+
226+
private:
227+
set<pair<int, int>, cmp> ts;
228+
unordered_map<int, int> left;
229+
unordered_map<int, int> right;
230+
int n;
231+
232+
void add(pair<int, int> s) {
233+
ts.insert(s);
234+
left[s.second] = s.first;
235+
right[s.first] = s.second;
236+
}
237+
238+
void del(pair<int, int> s) {
239+
ts.erase(s);
240+
left.erase(s.second);
241+
right.erase(s.first);
242+
}
243+
};
244+
245+
/**
246+
* Your ExamRoom object will be instantiated and called as such:
247+
* ExamRoom* obj = new ExamRoom(n);
248+
* int param_1 = obj->seat();
249+
* obj->leave(p);
250+
*/
251+
```
252+
253+
### **Go**
254+
255+
```go
256+
type ExamRoom struct {
257+
rbt *redblacktree.Tree
258+
left map[int]int
259+
right map[int]int
260+
n int
261+
}
262+
263+
func Constructor(n int) ExamRoom {
264+
dist := func(s []int) int {
265+
if s[0] == -1 || s[1] == n {
266+
return s[1] - s[0] - 1
267+
}
268+
return (s[1] - s[0]) >> 1
269+
}
270+
cmp := func(a, b interface{}) int {
271+
x, y := a.([]int), b.([]int)
272+
d1, d2 := dist(x), dist(y)
273+
if d1 == d2 {
274+
return x[0] - y[0]
275+
}
276+
return d2 - d1
277+
}
278+
this := ExamRoom{redblacktree.NewWith(cmp), map[int]int{}, map[int]int{}, n}
279+
this.add([]int{-1, n})
280+
return this
281+
}
282+
283+
func (this *ExamRoom) Seat() int {
284+
s := this.rbt.Left().Key.([]int)
285+
p := (s[0] + s[1]) >> 1
286+
if s[0] == -1 {
287+
p = 0
288+
} else if s[1] == this.n {
289+
p = this.n - 1
290+
}
291+
this.del(s)
292+
this.add([]int{s[0], p})
293+
this.add([]int{p, s[1]})
294+
return p
295+
}
296+
297+
func (this *ExamRoom) Leave(p int) {
298+
l, _ := this.left[p]
299+
r, _ := this.right[p]
300+
this.del([]int{l, p})
301+
this.del([]int{p, r})
302+
this.add([]int{l, r})
303+
}
304+
305+
func (this *ExamRoom) add(s []int) {
306+
this.rbt.Put(s, struct{}{})
307+
this.left[s[1]] = s[0]
308+
this.right[s[0]] = s[1]
309+
}
310+
311+
func (this *ExamRoom) del(s []int) {
312+
this.rbt.Remove(s)
313+
delete(this.left, s[1])
314+
delete(this.right, s[0])
315+
}
60316
317+
/**
318+
* Your ExamRoom object will be instantiated and called as such:
319+
* obj := Constructor(n);
320+
* param_1 := obj.Seat();
321+
* obj.Leave(p);
322+
*/
61323
```
62324

63325
### **...**

0 commit comments

Comments
 (0)