5-栈和队列

Posted qmillet

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5-栈和队列相关的知识,希望对你有一定的参考价值。

题一:【用两个栈实现队列】

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

分析:栈-先进后出 队列-先进先出

知识点:Stack API

技术图片

 法一:暴力-一个栈存储push的数据,一个栈pop数据。每次push前将stack2中数据添加到stack1中,每次pop数据前将stack1中数据push到stack2中。

 1 import java.util.Stack;
 2 
 3 public class Solution {
 4     Stack<Integer> stack1 = new Stack<Integer>();
 5     Stack<Integer> stack2 = new Stack<Integer>();
 6     
 7     public void push(int node) {
 8         while(!stack2.empty()){
 9             stack1.push(stack2.pop());
10         }
11         stack1.push(node);
12     }
13     
14     public int pop() {
15         while(!stack1.empty()){
16             stack2.push(stack1.pop());
17         }
18         return stack2.pop();
19     }
20 }

 

 法二:没那么麻烦,push时直接将数据添加到stack1中;pop时先判断stack2是否为空,如果不为空直接弹出栈顶元素,如果为空,就将stack1中的元素转移到stack2中,再弹出stack2中的栈顶。

举例:

①{A},{}

②{A B},{}//直接添加B

③{},{B}//弹出,stack2为空,将stack1元素转移到stack2中再弹出栈顶

④{C D },{B}//直接添加 C D

 1 import java.util.Stack;
 2 
 3 public class Solution {
 4     Stack<Integer> stack1 = new Stack<Integer>();
 5     Stack<Integer> stack2 = new Stack<Integer>();
 6     
 7     public void push(int node) {
 8         stack1.push(node);
 9     }
10     
11     public int pop() {
12         if(stack2.empty()){
13             while(!stack1.empty()){
14                 stack2.push(stack1.pop());
15             }
16         }
17         return stack2.pop();
18     }
19 }

 

 


 

 

题二:【滑动窗口的最大值】

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

法一:暴力破解-O(n*size)-看滑动数组大小,太大了效率不行

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> maxInWindows(int [] num, int size)
 4     {
 5         ArrayList<Integer> list = new ArrayList<Integer>();
 6         if(size<=0) return list;
 7         for(int left=0,right=size-1;right<num.length;left++,right++){
 8             int max = num[left];
 9             for(int i=left+1;i<=right;i++){
10                 if(num[i]>max) max=num[i];
11             }
12             list.add(max);
13         }
14         return list;
15     }
16 }

 

法二:利用双端队列-O(N)

Step1.使用一个双端队列存储滑窗内元素的下标

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

queue

     

 

Step2.若queue为空,说明刚开始滑动,将num第一个元素的索引压入队列中。

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 queue

 0    

 

Step3.遍历num下一个元素num[1]=3,

  ①先判断当前索引位置减去队列最左边元素是否>=size,如果是,那么说明随着滑窗滑动,当前滑窗内的最大值滑出去了,已经不再这个滑窗内,这是需要将队列最左边元素弹出。(队列最左边为滑窗内最大值索引,判断是否有效)

  ②将当前元素与队列最右边的索引处的数组值对比,如果当前元素大于队列最右边对应的值,则将队列最右边的值弹出,直到找到对应值比当前元素值大的。(队列左边是最大的值,随着上述操作,会逐渐更新队列,滑出去或者新添加的值更大的话将会更新队列,保证队头对应值最大)

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

 1    

 

 

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

2    

---输出4

 

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

 2 3  

---输出4

 

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

4    

---输出6

 

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

4 5  

---输出6

 

value 2 3 4 2 6 2 5
index 0 1 2 3 4 5 6

 

4  5  

---输出6

 

value 2 3 4 2 6 2 5 1
index 0 1 2 3 4 5 6 7

 --当前索引处位置(7)-队列最左边(4)=size(3)--》滑出

 4 5 7

 --

5 7  

 --输出5

 1 import java.util.*;
 2 public class Solution {
 3     public ArrayList<Integer> maxInWindows(int [] num, int size)
 4     {
 5         ArrayList<Integer> list = new ArrayList<Integer>();
 6         if(num==null||size<=0) return list;
 7         ArrayDeque<Integer> queue = new ArrayDeque<Integer>();
 8         for(int i=0;i<num.length;i++){
 9             if(queue.isEmpty()){ //只有i=0,即刚开始遍历时才会为空
10                 queue.add(i);
11             }
12             if(i-queue.peekFirst()>=size){//判断队头是否还在滑窗内
13                 queue.pollFirst();
14             }
15             while(!queue.isEmpty()&&num[i]>=num[queue.peekLast()]){//排除比新遍历元素还小的对应索引值
16                 queue.pollLast();
17             }
18             queue.addLast(i);
19             if(i>=size-1){//从第size-1个元素开始,就要输出了
20                 list.add(num[queue.peekFirst()]);
21             }
22             
23         }
24         return list;
25     }
26 }

 

 

 

 知识点:ArrayDeque API

 技术图片

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于5-栈和队列的主要内容,如果未能解决你的问题,请参考以下文章

数据结构栈和队列,看完这一篇就够了(万字配动图配习题)

[数据结构]栈和队列的内容分析与讲解

考研数据结构与算法栈和队列

[程序员代码面试指南]栈和队列-生成窗口最大值数组(双端队列)

5-栈和队列

Java栈和队列·下