用两个栈实现队列

//需要考虑S2是否为空
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
//队列的压入就是s1的压入数据
public void push(int node) {
stack1.push(node);
}
//弹出借助于S1/s2 两个 弹出需要考虑队列是否为空
public int pop() {
if(size()!=0){
if(stack2.empty()){ //若s2为空 则需要把s1的元素全部压入s2再输出
while(!stack1.empty())
stack2.push(stack1.pop());
}
return stack2.pop(); //若s2不为空 则直接输出
}else{
System.out.println("队列为空,不能执行出队操作");
return -1;
}
}
//队列的大小 队列为空则说明 s1/s2均为空
public int size(){
return stack1.size()+stack2.size();
}
}用两个队列实现一个栈



import java.util.*;
/**
* 使用LinkedList表示队列 所以队列从尾入队 q1.addLast(e) 从头出队q1.removeFirst()
* @author 多多
*
* @param <E>
*/
public class MyStack<E> {
LinkedList<E> q1=new LinkedList<E>(); //队列1
LinkedList<E> q2=new LinkedList<E>(); //队列2
//入栈操作 即入队
public void push(E e) {
q1.addLast(e); //从尾部入队
}
//出栈操作: 非空队列的n-1个压入空队列 剩余的第n个出队 总有一个队列为空
public E pop() {
if(size()!=0) { //判断栈是否为空
if(!q1.isEmpty()) {
putN_1ToAnother(); //非空队列的n-1个压入空队列
return q1.removeFirst(); //剩余的第n个出队 (从对头出队)
}else {
putN_1ToAnother();
return q2.removeFirst();
}
}else {
System.out.println("栈为空,无法执行出栈操作");
return null;
}
}
// 非空队列的n-1个压入空队列
private void putN_1ToAnother() {
if(!q1.isEmpty()) { //若q2为空 则从q1中移动前n-1个
while(q1.size()>1) {
q2.addLast(q1.removeFirst());
}
}else {
while(q2.size()>1) { //若q1为空 则从q2中移动前n-1个
q1.addLast(q2.removeFirst());
}
}
}
//判断栈是否为空
public int size() {
return q1.size()+q2.size();
}
}包含min函数的栈

方法1: 每次都存入
import java.util.Stack;
public class Solution {
private Stack<Integer> stackDate;
private Stack<Integer> stackMin;
public Solution(){
stackDate = new Stack<>();
stackMin = new Stack<>();
}
public void push(int node) {
stackDate.push(node);
if(stackMin.isEmpty()){
stackMin.push(node);
}else if(node <= stackMin.peek()){
stackMin.push(node);
}
}
public void pop() {
if(stackDate.isEmpty()){
throw new RuntimeException("This stack is empty!");
}
if(stackDate.peek() == stackMin.peek()){
stackMin.pop();
}
stackDate.pop();
}
public int top() {
if(stackDate.isEmpty()){
throw new RuntimeException("This stack is empty!");
}
int value = stackDate.pop();
if(value == stackMin.peek()){
stackMin.pop();
}
return value;
}
public int min() {
if(stackMin.isEmpty()){
throw new RuntimeException("This stack is empty!");
}else{
return stackMin.peek();
}
}
}方法2:只存入比之前小的元素
import java.util.Stack;
public class Solution {
private Stack<Integer> stackDate;
private Stack<Integer> stackMin;
public Solution(){
stackDate = new Stack<Integer>();
stackMin = new Stack<Integer>();
}
public void push(int node) {
stackDate.push(node);
if(stackMin.isEmpty()){
stackMin.push(node);
}else if(node <= stackMin.peek()){
stackMin.push(node);
}
}
public void pop() {
if(stackDate.empty()){
throw new RuntimeException("This stack is empty!");
}
if(stackDate.peek() == stackMin.peek()){ //相同则一起弹出
stackMin.pop();
}
stackDate.pop(); //否则只是弹出数据栈
}
public int top() { //获取栈顶元素
if(stackDate.isEmpty()){
throw new RuntimeException("This stack is empty!");
}
int value = stackDate.pop();
if(value == stackMin.peek()){
stackMin.pop();
}
return value;
}
public int min() {
if(stackMin.isEmpty()){
throw new RuntimeException("This stack is empty!");
}else{
return stackMin.peek();
}
}
}栈的压入 ,弹出序列


方法1: Stack结构辅助
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0 || popA.length==0|| pushA.length!=popA.length)
return false;
Stack<Integer> s=new Stack<Integer>();
int index=0; //pop数组的下标
for(int i=0;i<pushA.length;i++){
s.push(pushA[i]); //压入元素
//判断 当s非空 且栈顶元素等于pop[index]时则弹出
while(!s.empty() && s.peek()==popA[index]){
s.pop();
index++;
}
}
return s.empty(); //正常则全部弹出 为空 否则为不正确的输出序列
}
}//注意一个地方:while(index<popA.length && s.peek()==popA[index]){ //这个就是防止两个数组均对应输出完毕 出现栈为空 却要弹出的情况
s.pop();
index++;
}滑动窗口的最大值:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
方法1 :时间O(n2) 两个for截取特定区间比较储存
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
//采用时间复杂度为O(n2)的笨办法
ArrayList<Integer> list=new ArrayList<Integer>();
if(num==null || num.length==0 || size<=0 || size> num.length)
return list;
int len=num.length;
for(int i=0;i<len-size+1;i++){
int max=Integer.MIN_VALUE;
for(int j=i;j< i+size; j++){ //注意这个区间截取范围
if(max< num[j])
max=num[j];
}
list.add(max);
}
return list;
}
}方法2 :时间O(n) 空间O(n) 采用队列的思想
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> list=new ArrayList<Integer>();
if(num==null || num.length==0 || size<=0 || size> num.length)
return list;
int len=num.length;
//采用队列的思想 入队一个出队一个
Queue<Integer> q=new LinkedList<Integer>();
int max=Integer.MIN_VALUE;
//对于前size个元素 直接一次入队列
for(int i=0;i<size;i++){
q.add(num[i]);
if(max <num[i])
max=num[i];
}
list.add(max);
//之后每次弹出一个 就进入一个 并在其中取最大值
for(int i=size;i<len;i++){
q.poll();
q.add(num[i]);
max=Integer.MIN_VALUE;
for(Integer n: q){
if(max< n)
max=n;
}
list.add(max);
}
return list;
}
}
方法3 :时间,空间均为O(n) 采用“双端队列”的思想
原则: * 对新来的元素k,将其与双端队列中的元素相比较 * 1)前面比k小的,直接移出队列(因为不再可能成为后面滑动窗口的最大值了!), * 2)前面比k大的X,比较两者下标,判断X是否已不在窗口之内,不在了,直接移出队列 * 队列的第一个元素是滑动窗口中的最大值import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
ArrayList<Integer> list=new ArrayList<Integer>();
if(num==null || num.length==0 || size<=0 || size> num.length)
return list;
int len=num.length;
//采用队列的思想 入队一个出队一个
LinkedList<Integer> q=new LinkedList<Integer>(); //队列存储的是下标
for(int i=0;i<len;i++){
//从后面依次弹出队列中比当前num值小的元素 则当前队列首元素即为当前窗口的最大值
while(!q.isEmpty() && num[q.peekLast()]<= num[i]){ //注意队列不为空的判断!!因为第一次是没有元素的,会主动跳过两个判断
q.pollLast();
}
//当前窗口首元素位置移出当前窗口 则删除首元素
while(!q.isEmpty() && i-q.peekFirst()>size-1){
q.pollFirst();
}
q.addLast(i); //将每一个num值入队
if(size!=0 && i>=size-1){ //当i >=size-1时才开始写入窗口最大值
list.add(num[q.peekFirst()]);
}
}
return list;
}
}
本文介绍如何使用两个栈实现队列的功能,以及如何利用两个队列实现栈,并探讨了包含min函数的栈的设计方法,此外还讲解了栈的压入弹出序列验证以及滑动窗口最大值的多种高效算法。

被折叠的 条评论
为什么被折叠?



