Skip to content

Commit 6182d5d

Browse files
committed
feat: add solutions to lc problem: No.1172
No.1172.Dinner Plate Stacks
1 parent aebad32 commit 6182d5d

File tree

6 files changed

+650
-0
lines changed

6 files changed

+650
-0
lines changed

solution/1100-1199/1172.Dinner Plate Stacks/README.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,258 @@ D.pop() // 返回 -1。仍然没有栈。
7777

7878
<!-- 这里可写通用的实现逻辑 -->
7979

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+
80105
<!-- tabs:start -->
81106

82107
### **Python3**
83108

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

86111
```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)
87134

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)
88153
```
89154

90155
### **Java**
91156

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

94159
```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+
}
95324

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+
*/
96332
```
97333

98334
### **...**

0 commit comments

Comments
 (0)