1.由两个栈组成队列
题目要求:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
)
难度:✨
解答:
- stpush 一个栈做压入栈,对尾加入数据时只向这个栈压入数据
- stpop 一个栈作为弹出栈,对头弹出数据时只从这个栈弹出
-
因为数据压入栈的时候,顺序是先进后出的。那么只要把stackPush 的数据再压入stackPop 中,顺序就变回来了。
-
-
1.如果stackPush要往stackPop 中压入数据,那么必须一次性把 stackPush中的数据全部压入。 -
2.如果stackPop不为空,stackPush绝对不能向stackPop 中压入数据。
-
class MyQueue {
public Stack<Integer> stpush;
public Stack<Integer> stpop;
public MyQueue() {
stpush = new Stack<Integer>();//入队
stpop = new Stack<Integer>();//出队
}
public void push(int x) {
stpush.push(x);
}
public int pop() {
if(stpop.empty()&&stpush.empty()){ //都为空
throw new RuntimeException("empty");
}else if(stpop.empty()){
while(!stpush.empty()){ //pop栈 空但push栈不空 将push栈所有元素倒入pop
stpop.push(stpush.pop());
}
}
return stpop.pop();
}
public int peek() {
if(stpop.empty()&&stpush.empty()){ //都为空
throw new RuntimeException("enpty");
}else if(stpop.empty()){
while(!stpush.empty()){ //pop 空但push不空 将push栈所有元素倒入pop
stpop.push(stpush.pop());
}
}
return stpop.peek();
}
public boolean empty() {
if(stpop.empty()&&stpush.empty()){
return true;
}else{
return false;
}
}
}
2.滑动窗口的最大值
题目要求:
难度:✨✨✨
解答:使用单调递减队列
- 先填满窗口的前 k - 1,然后再挨个处理
- PUSH 方法在队尾添加元素
- 当nums[i]>队尾元素时:先要把前面比自己小的元素都删掉,再加入队尾
- 当nums[i]<队尾元素时:放弃加入 (因为已经时递减队列 若nums[i]比最小的都小 则不可能成为最大值)
-
- 用ArrayList 记录此时队列中最大的元素
- 从队列中删除nums[i-k+1] 即窗口对应数组的最左端元素。 POP方法在队头删除元素N ,要判断
data.getFirst() == n
,是因为我们想删除的队头元素n
可能已经被「压扁」了,可能已经不存在了,所以这时候就不用删除了 - 遍历结束后 将ArrayList值导出到数组返回
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums== null|| k<1|| nums.length<k){
return null;
}
MonotonicQueue window = new MonotonicQueue();
List<Integer> res = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (i < k - 1) {
//先填满窗口的前 k - 1
window.push(nums[i]);
} else {
// 窗口向前滑动,加入新数字
window.push(nums[i]);
// 记录当前窗口的最大值
res.add(window.max());
// 移出旧数字
window.pop(nums[i - k + 1]);
}
}
// 需要转成 int[] 数组再返回
int[] arr = new int[res.size()];
for (int i = 0; i < res.size(); i++) {
arr[i] = res.get(i);
}
return arr;
}
/* 单调队列的实现 */
class MonotonicQueue {
LinkedList<Integer> maxq = new LinkedList<>();
public void push(int n) {
// 将小于 n 的元素全部删除
while (!maxq.isEmpty() && maxq.getLast() < n) {
maxq.pollLast();
}
// 然后将 n 加入尾部
maxq.addLast(n);
}
public int max() {
return maxq.getFirst();
}
public void pop(int n) {
if (n == maxq.getFirst()) {
maxq.pollFirst();
}
}
}
}