@@ -42,22 +42,284 @@ seat() -> 5,学生最后坐在 5 号座位上。
42
42
43
43
<!-- 这里可写通用的实现逻辑 -->
44
44
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
+
45
55
<!-- tabs:start -->
46
56
47
57
### ** Python3**
48
58
49
59
<!-- 这里可写当前语言的特殊实现逻辑 -->
50
60
51
61
``` 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))
52
95
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)
53
111
```
54
112
55
113
### ** Java**
56
114
57
115
<!-- 这里可写当前语言的特殊实现逻辑 -->
58
116
59
117
``` 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
+ }
60
316
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
+ */
61
323
```
62
324
63
325
### ** ...**
0 commit comments