一、JZ9 用两个栈实现队列(简单)
1、使用两个栈,一个栈用来装放进来的数据,一个栈用来输出结果,输出结果的栈没有数据时,就将放数据的栈的数据全部转过去输出结果的栈。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack2.isEmpty()) {
while(!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
if(stack2.isEmpty()) {
return 0;
} else {
return stack2.pop();
}
}
}
二、JZ30 包含min函数的栈(简单)
1、获取栈顶方法时就取出一个值获取到再放进去,获取最小值就使用一个辅助ArrayList记录栈中的值,调用min方法时就进行遍历比较取最小值
import java.util.Stack;
import java.util.ArrayList;
public class Solution {
Stack<Integer> stack = new Stack<>();
ArrayList<Integer> list = new ArrayList<>();
public void push(int node) {
stack.push(node);
list.add(node);
}
public void pop() {
stack.pop();
list.remove(list.size() -1);
}
public int top() {
return stack.peek();
}
public int min() {
int min = list.get(0);
for(int node: list) {
if(node < min) {
min = node;
}
}
return min;
}
}
2、使用辅助栈
import java.util.Stack;
public class Solution {
//用于栈的push 与 pop
Stack<Integer> s1 = new Stack<Integer>();
//用于存储最小min
Stack<Integer> s2 = new Stack<Integer>();
public void push(int node) {
s1.push(node);
//空或者新元素较小,则入栈
if(s2.isEmpty() || s2.peek() > node)
s2.push(node);
else
//重复加入栈顶
s2.push(s2.peek());
}
public void pop() {
s1.pop();
s2.pop();
}
public int top() {
return s1.peek();
}
public int min() {
return s2.peek();
}
}
三、JZ31 栈的压入、弹出序列(中等)
1、创建一个栈,通过循环去判断栈顶元素是否等于当前循环中出栈的元素,不等的时候一直入栈入栈数组中的数据,最后判断该栈是否全部数据出栈完即栈是否为空。
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> stack = new Stack<>();
int n =popA.length;
int j = 0;
for(int i=0;i<n;i++) {
while(j<n && (stack.isEmpty() || stack.peek() != popA[i])) {
stack.push(pushA[j]);
j++;
}
if(stack.peek() == popA[i]) {
stack.pop();
}
}
return stack.isEmpty();
}
}
四、JZ73 翻转单词序列(简单)
1、先将字符串通过split(" ")分割加入栈,然后再全部出栈拼成一个新的字符串
import java.util.Stack;
public class Solution {
public String ReverseSentence(String str) {
Stack<String> stack = new Stack<>();
for(String item: str.split(" ")) {
stack.push(item);
}
StringBuilder builder = new StringBuilder();
while(!stack.isEmpty()) {
builder.append(stack.pop() + " ");
}
return builder.toString().trim();
}
}
五、JZ59 滑动窗口的最大值(较难)
1、暴力法,直接使用双重遍历,用ArrayList装每个窗口对应的最大值并最终返回
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> result = new ArrayList<>();
if(num.length > 0 && size > 0) {
for(int i=0;i < num.length - size + 1;i++) {
int temp = num[i];
for(int j=i;j < (i+size);j++) {
if(num[j] > temp) temp = num[j];
}
result.add(temp);
}
}
return result;
}
}
2、使用双向队列:step 1:维护一个双向队列,用来存储数列的下标。step 2:首先检查窗口大小与数组大小。step 3:先遍历第一个窗口,如果即将进入队列的下标的值大于队列后方的值,依次将小于的值拿出来去掉,再加入,保证队列是递增序。step 4:遍历后续窗口,每次取出队首就是最大值,如果某个下标已经过了窗口,则从队列前方将其弹出。step 5:对于之后的窗口,重复step 3,直到数组结束。
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> res = new ArrayList<Integer>();
//窗口大于数组长度的时候,返回空
if(size <= num.length && size != 0){
//双向队列
ArrayDeque <Integer> dq = new ArrayDeque<Integer>();
//先遍历一个窗口
for(int i = 0; i < size; i++){
//去掉比自己先进队列的小于自己的值
while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
dq.pollLast();
dq.add(i);
}
//遍历后续数组元素
for(int i = size; i < num.length; i++){
//取窗口内的最大值
res.add(num[dq.peekFirst()]);
while(!dq.isEmpty() && dq.peekFirst() < (i - size + 1))
//弹出窗口移走后的值
dq.pollFirst();
//加入新的值前,去掉比自己先进队列的小于自己的值
while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
dq.pollLast();
dq.add(i);
}
res.add(num[dq.pollFirst()]);
}
return res;
}
}