@@ -77,22 +77,258 @@ D.pop() // 返回 -1。仍然没有栈。
77
77
78
78
<!-- 这里可写通用的实现逻辑 -->
79
79
80
+ ** 方法一:栈数组 + 有序集合**
81
+
82
+ 我们定义以下数据结构或变量:
83
+
84
+ - ` capacity ` :每个栈的容量;
85
+ - ` stacks ` :栈数组,用于存储所有的栈,其中每个栈的最大容量都是 ` capacity ` ;
86
+ - ` not_full ` :有序集合,用于存储所有未满的栈在栈数组中的下标。
87
+
88
+ 对于 ` push(val) ` 操作:
89
+
90
+ - 我们首先判断 ` not_full ` 是否为空,如果为空,则说明没有未满的栈,需要新建一个栈,然后将 ` val ` 压入该栈中,此时判断容量 ` capacity ` 是否大于 $1$,如果大于 $1$,则将该栈的下标加入 ` not_full ` 中。
91
+ - 如果 ` not_full ` 不为空,则说明有未满的栈,我们取出 ` not_full ` 中最小的下标 ` index ` ,将 ` val ` 压入 ` stacks[index] ` 中,此时如果 ` stacks[index] ` 的容量等于 ` capacity ` ,则将 ` index ` 从 ` not_full ` 中删除。
92
+
93
+ 对于 ` popAtStack(index) ` 操作:
94
+
95
+ - 我们首先判断 ` index ` 是否在 ` stacks ` 的下标范围内,如果不在,则直接返回 $-1$。如果 ` stacks[index] ` 为空,同样直接返回 $-1$。
96
+ - 如果 ` stacks[index] ` 不为空,则取出 ` stacks[index] ` 的栈顶元素 ` val ` ,并将其从栈中删除。如果 ` index ` 等于 ` stacks ` 的长度减 $1$,则说明 ` stacks[index] ` 是最后一个栈,如果此时 ` stacks[index] ` 为空,我们循环将 ` index ` 从 ` stacks ` 中删除,并且将 ` index ` 从 ` not_full ` 中删除,直到 ` stacks[index] ` 不为空或者 ` stacks ` 为空为止。否则,如果 ` stacks[index] ` 不是最后一个栈,我们将 ` index ` 加入 ` not_full ` 中。
97
+ - 最后返回 ` val ` 。
98
+
99
+ 对于 ` pop() ` 操作:
100
+
101
+ - 我们直接调用 ` popAtStack(stacks.length - 1) ` 即可。
102
+
103
+ 时间复杂度 $(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 为操作次数。
104
+
80
105
<!-- tabs:start -->
81
106
82
107
### ** Python3**
83
108
84
109
<!-- 这里可写当前语言的特殊实现逻辑 -->
85
110
86
111
``` python
112
+ from sortedcontainers import SortedSet
113
+
114
+
115
+ class DinnerPlates :
116
+ def __init__ (self , capacity : int ):
117
+ self .capacity = capacity
118
+ self .stacks = []
119
+ self .not_full = SortedSet()
120
+
121
+ def push (self , val : int ) -> None :
122
+ if not self .not_full:
123
+ self .stacks.append([val])
124
+ if self .capacity > 1 :
125
+ self .not_full.add(len (self .stacks) - 1 )
126
+ else :
127
+ index = self .not_full[0 ]
128
+ self .stacks[index].append(val)
129
+ if len (self .stacks[index]) == self .capacity:
130
+ self .not_full.discard(index)
131
+
132
+ def pop (self ) -> int :
133
+ return self .popAtStack(len (self .stacks) - 1 )
87
134
135
+ def popAtStack (self , index : int ) -> int :
136
+ if index < 0 or index >= len (self .stacks) or not self .stacks[index]:
137
+ return - 1
138
+ val = self .stacks[index].pop()
139
+ if index == len (self .stacks) - 1 and not self .stacks[- 1 ]:
140
+ while self .stacks and not self .stacks[- 1 ]:
141
+ self .not_full.discard(len (self .stacks) - 1 )
142
+ self .stacks.pop()
143
+ else :
144
+ self .not_full.add(index)
145
+ return val
146
+
147
+
148
+ # Your DinnerPlates object will be instantiated and called as such:
149
+ # obj = DinnerPlates(capacity)
150
+ # obj.push(val)
151
+ # param_2 = obj.pop()
152
+ # param_3 = obj.popAtStack(index)
88
153
```
89
154
90
155
### ** Java**
91
156
92
157
<!-- 这里可写当前语言的特殊实现逻辑 -->
93
158
94
159
``` java
160
+ class DinnerPlates {
161
+ private int capacity;
162
+ private List<Deque<Integer > > stacks = new ArrayList<> ();
163
+ private TreeSet<Integer > notFull = new TreeSet<> ();
164
+
165
+ public DinnerPlates (int capacity ) {
166
+ this . capacity = capacity;
167
+ }
168
+
169
+ public void push (int val ) {
170
+ if (notFull. isEmpty()) {
171
+ stacks. add(new ArrayDeque<> ());
172
+ stacks. get(stacks. size() - 1 ). push(val);
173
+ if (capacity > 1 ) {
174
+ notFull. add(stacks. size() - 1 );
175
+ }
176
+ } else {
177
+ int index = notFull. first();
178
+ stacks. get(index). push(val);
179
+ if (stacks. get(index). size() == capacity) {
180
+ notFull. pollFirst();
181
+ }
182
+ }
183
+ }
184
+
185
+ public int pop () {
186
+ return popAtStack(stacks. size() - 1 );
187
+ }
188
+
189
+ public int popAtStack (int index ) {
190
+ if (index < 0 || index >= stacks. size() || stacks. get(index). isEmpty()) {
191
+ return - 1 ;
192
+ }
193
+ int val = stacks. get(index). pop();
194
+ if (index == stacks. size() - 1 && stacks. get(stacks. size() - 1 ). isEmpty()) {
195
+ while (! stacks. isEmpty() && stacks. get(stacks. size() - 1 ). isEmpty()) {
196
+ notFull. remove(stacks. size() - 1 );
197
+ stacks. remove(stacks. size() - 1 );
198
+ }
199
+ } else {
200
+ notFull. add(index);
201
+ }
202
+ return val;
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Your DinnerPlates object will be instantiated and called as such:
208
+ * DinnerPlates obj = new DinnerPlates(capacity);
209
+ * obj.push(val);
210
+ * int param_2 = obj.pop();
211
+ * int param_3 = obj.popAtStack(index);
212
+ */
213
+ ```
214
+
215
+ ### ** C++**
216
+
217
+ ``` cpp
218
+ class DinnerPlates {
219
+ public:
220
+ DinnerPlates(int capacity) {
221
+ this->capacity = capacity;
222
+ }
223
+
224
+ void push(int val) {
225
+ if (notFull.empty()) {
226
+ stacks.emplace_back(stack<int>());
227
+ stacks.back().push(val);
228
+ if (capacity > 1) {
229
+ notFull.insert(stacks.size() - 1);
230
+ }
231
+ } else {
232
+ int index = *notFull.begin();
233
+ stacks[index].push(val);
234
+ if (stacks[index].size() == capacity) {
235
+ notFull.erase(index);
236
+ }
237
+ }
238
+ }
239
+
240
+ int pop() {
241
+ return popAtStack(stacks.size() - 1);
242
+ }
243
+
244
+ int popAtStack(int index) {
245
+ if (index < 0 || index >= stacks.size() || stacks[index].empty()) {
246
+ return -1;
247
+ }
248
+ int val = stacks[index].top();
249
+ stacks[index].pop();
250
+ if (index == stacks.size() - 1 && stacks[index].empty()) {
251
+ while (!stacks.empty() && stacks.back().empty()) {
252
+ notFull.erase(stacks.size() - 1);
253
+ stacks.pop_back();
254
+ }
255
+ } else {
256
+ notFull.insert(index);
257
+ }
258
+ return val;
259
+ }
260
+
261
+ private:
262
+ int capacity;
263
+ vector<stack<int >> stacks;
264
+ set<int > notFull;
265
+ };
266
+
267
+ /* *
268
+ * Your DinnerPlates object will be instantiated and called as such:
269
+ * DinnerPlates* obj = new DinnerPlates(capacity);
270
+ * obj->push(val);
271
+ * int param_2 = obj->pop();
272
+ * int param_3 = obj->popAtStack(index);
273
+ */
274
+ ```
275
+
276
+ ### ** Go**
277
+
278
+ ``` go
279
+ type DinnerPlates struct {
280
+ capacity int
281
+ stacks [][]int
282
+ notFull *redblacktree.Tree
283
+ }
284
+
285
+ func Constructor (capacity int ) DinnerPlates {
286
+ return DinnerPlates{capacity: capacity, notFull: redblacktree.NewWithIntComparator ()}
287
+ }
288
+
289
+ func (this *DinnerPlates ) Push (val int ) {
290
+ if this.notFull .Size () == 0 {
291
+ this.stacks = append (this.stacks , []int {val})
292
+ if this.capacity > 1 {
293
+ this.notFull .Put (len (this.stacks )-1 , nil )
294
+ }
295
+ } else {
296
+ index , _ := this.notFull .Left ().Key .(int )
297
+ this.stacks [index] = append (this.stacks [index], val)
298
+ if len (this.stacks [index]) == this.capacity {
299
+ this.notFull .Remove (index)
300
+ }
301
+ }
302
+ }
303
+
304
+ func (this *DinnerPlates ) Pop () int {
305
+ return this.PopAtStack (len (this.stacks ) - 1 )
306
+ }
307
+
308
+ func (this *DinnerPlates ) PopAtStack (index int ) int {
309
+ if index < 0 || index >= len (this.stacks ) || len (this.stacks [index]) == 0 {
310
+ return -1
311
+ }
312
+ val := this.stacks [index][len (this.stacks [index])-1 ]
313
+ this.stacks [index] = this.stacks [index][:len (this.stacks [index])-1 ]
314
+ if index == len (this.stacks )-1 && len (this.stacks [index]) == 0 {
315
+ for len (this.stacks ) > 0 && len (this.stacks [len (this.stacks )-1 ]) == 0 {
316
+ this.notFull .Remove (len (this.stacks ) - 1 )
317
+ this.stacks = this.stacks [:len (this.stacks )-1 ]
318
+ }
319
+ } else {
320
+ this.notFull .Put (index, nil )
321
+ }
322
+ return val
323
+ }
95
324
325
+ /* *
326
+ * Your DinnerPlates object will be instantiated and called as such:
327
+ * obj := Constructor(capacity);
328
+ * obj.Push(val);
329
+ * param_2 := obj.Pop();
330
+ * param_3 := obj.PopAtStack(index);
331
+ */
96
332
```
97
333
98
334
### ** ...**
0 commit comments