餐盘栈
难度:
标签:
题目描述
代码结果
运行时间: 438 ms, 内存: 91.9 MB
/*
* 思路:
* 1. 使用List和Optional处理栈的数据结构。
* 2. push方法将元素推入第一个非满栈,或创建新栈。
* 3. pop方法返回第一个非空栈的栈顶元素。
* 4. popAtStack方法从指定栈中返回栈顶元素。
*/
import java.util.*;
import java.util.stream.*;
class DinnerPlates {
private List<Stack<Integer>> stacks;
private int capacity;
private PriorityQueue<Integer> available;
public DinnerPlates(int capacity) {
this.capacity = capacity;
this.stacks = new ArrayList<>();
this.available = new PriorityQueue<>();
}
public void push(int val) {
if (!available.isEmpty() && available.peek() < stacks.size()) {
int index = available.poll();
stacks.get(index).push(val);
if (stacks.get(index).size() == capacity) {
available.remove(index);
}
} else {
Stack<Integer> stack = new Stack<>();
stack.push(val);
stacks.add(stack);
if (capacity > 1) available.add(stacks.size() - 1);
}
}
public int pop() {
return IntStream.rangeClosed(1, stacks.size())
.mapToObj(i -> stacks.get(stacks.size() - i))
.filter(s -> !s.isEmpty())
.findFirst()
.map(s -> {
int val = s.pop();
if (s.size() == capacity - 1) available.add(stacks.size() - 1);
return val;
})
.orElse(-1);
}
public int popAtStack(int index) {
if (index >= stacks.size() || stacks.get(index).isEmpty()) return -1;
int val = stacks.get(index).pop();
if (stacks.get(index).size() == capacity - 1) available.add(index);
return val;
}
}
解释
方法:
该题解使用了多个栈和一个有序集合来实现餐盘类。主要思路如下:
1. 用一个列表 `stack` 来存储所有的餐盘,每个餐盘用一个整数表示。
2. 用一个列表 `top` 来存储每个栈的栈顶位置。
3. 用一个有序集合 `poppedPos` 来存储被弹出的位置。
4. 对于 `push` 操作,如果有被弹出的位置,就将新餐盘放到最左边的被弹出位置;否则,将新餐盘放到最右边的栈上。
5. 对于 `pop` 操作,从最右边的栈开始弹出餐盘,并更新 `top` 和 `poppedPos`。
6. 对于 `popAtStack` 操作,根据给定的栈编号计算出餐盘在 `stack` 中的位置,将其弹出,并更新 `top` 和 `poppedPos`。
时间复杂度:
O(log n),其中 n 为调用 `push` 的次数。
空间复杂度:
O(n),其中 n 为调用 `push` 的次数。
代码细节讲解
🦆
在实现 `DinnerPlates` 类的 `push` 操作时,你如何确定被弹出的位置是否真的是空的,以便放置新的餐盘?
▷🦆
对于 `pop` 操作,如何处理在有序集合 `poppedPos` 中删除元素的逻辑,特别是当最右边的餐盘已被弹出时你的处理方式是什么?
▷🦆
在 `popAtStack` 方法中,如果栈顶的餐盘已被弹出,但栈中仍有其他餐盘,此时如何确保返回正确的餐盘值?
▷