当前位置:   article > 正文

【数据结构】栈和队列面试题总结(持续更新中...)_栈和队列的相关问题

栈和队列的相关问题

目录

一、栈相关基础概念

二、队列相关基础概念

三、OJ题

3.1 不可能的出栈顺序

3.2 中缀表达式

3.3 括号匹配

3.4 逆波兰表达式求值

3.5 出栈入栈次序匹配

3.6 循环队列

3.7 用队列实现栈

3.8 用栈实现队列

3.9 最小栈


一、栈相关基础概念

① 先进先入。不是所有进完才可以出,入的同时也可以出

②用数组实现栈:入栈和出栈的时间复杂度是O(1)

③用单链表实现栈:

头插法: 入栈和出栈 O(1)

尾插法:入栈和出栈 O(n)

所以用单链表实现栈时一定要头入头出

④方法  push、peek、pop、size、empty

二、队列相关基础概念

① 队尾进,队头出。底层是个双向链表。

②Queue是个接口,在实例化时必须实例化LinkedList的对象。

        Queue<Integer> q = new LinkedList<>();

③用单链表实现队列  ok

④ 用数组实现队列 。必须使用循环数组。后面3.6有代码实现逻辑。

④方法  offer、poll、peek、size、isEmpty

三、OJ

3.1 不可能的出栈顺序

核心:入的时候同时可以出

3.2 中缀表达式

中缀转后缀:按照自己的理解,从左往右加括号,先乘除后加减。再逐步将运算符移到括号后,移

                        掉所有的(),就是rug

计算中缀表达式的值:遇见数字入栈,遇到运算符就从栈出两个元素。先出的放在运算符的后面,后出栈的放在运算符前面。将计算结果再入栈。

3.3 括号匹配

 OJ链接:20. 有效的括号 - 力扣(LeetCode)

实现代码:

  1. class Solution {
  2. public boolean isValid(String s) {
  3. Stack<Character> stack = new Stack<>();
  4. for(int i = 0 ;i<s.length();i++){
  5. char ch = s.charAt(i);
  6. // 遇见左括号就入栈,注意是单引号
  7. if(ch == '[' || ch == '{' || ch == '('){
  8. stack.push(ch);
  9. }else{
  10. // 否则,就与栈顶元素进行比较
  11. // 如果栈是空的,并且遇见的是右括号,直接返回false
  12. // 判断栈空 不能使用stack==null
  13. if(stack.isEmpty()){
  14. return false;
  15. }else{
  16. char peek = stack.pop();
  17. if( (peek == '[' && ch == ']') || (peek == '{' && ch == '}') || (peek == '(' && ch ==')')){
  18. continue;
  19. }else{
  20. return false;
  21. }
  22. }
  23. }
  24. }
  25. if(stack.isEmpty()){
  26. return true;
  27. }else{
  28. return false;
  29. }
  30. }
  31. }

3.4 逆波兰表达式求值

 OJ链接:150. 逆波兰表达式求值 - 力扣(LeetCode)

实现代码:

  1. class Solution {
  2. public int evalRPN(String[] tokens) {
  3. Stack<Integer> stack = new Stack<>();
  4. HashSet<String> set = new HashSet<>();
  5. set.add("+");
  6. set.add("-");
  7. set.add("*");
  8. set.add("/");
  9. for(String str:tokens){
  10. // 如果遇见的是不是运算符,是数字,就入栈
  11. if(!set.contains(str)){
  12. stack.push(Integer.parseInt(str));
  13. }else{
  14. // 遇见运算符,就弹出两个数字
  15. int back = stack.pop();
  16. int front = stack.pop();
  17. HashMap<String,Integer> hashMap = new HashMap<>();
  18. hashMap.put("+",front+back);
  19. hashMap.put("-",front-back);
  20. hashMap.put("*",front*back);
  21. // 注意:back有可能为 0
  22. if(back != 0){
  23. hashMap.put("/",front/back);
  24. }
  25. //计算结果,将结果入栈
  26. int result = hashMap.get(str);
  27. stack.push(result);
  28. }
  29. }
  30. return stack.peek();
  31. }
  32. }

3.5 出栈入栈次序匹配

 OJ链接:栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)

 解题思路:

要点1:定义一个pos,记录popA数组中元素的位置。

要点2:遍历pushA,依次将pushA中的元素入栈,判断栈顶元素和popA中的元素是否相同,相同就出栈,并观察popA中的下一个元素是否和新栈顶元素相等。如果不相等,入栈pushA的下一个元素

实现代码:

  1. import java.util.*;
  2. import java.util.ArrayList;
  3. public class Solution {
  4. public boolean IsPopOrder(int [] pushA,int [] popA) {
  5. Stack<Integer> stack1 = new Stack();
  6. int pos = 0;
  7. for(int i=0;i<pushA.length;i++){
  8. stack1.push(pushA[i]);
  9. while(!stack1.isEmpty() && stack1.peek() == popA[pos]){
  10. stack1.pop();
  11. pos++;
  12. }
  13. }
  14. if(stack1.empty()){
  15. return true;
  16. }
  17. return false;
  18. }
  19. }

3.6 循环队列

 OJ链接:622. 设计循环队列 - 力扣(LeetCode)

 解题思路:

要点1:为了区分队列空和满,约定:

        rear指向数组最后一个元素的下一个位置,下一次添加数据,可以直接往rear位置上放

        front == rear 队列空

        rear的下一个元素是front,队列满了。(rear+1)%elem.length

要点2:返回队列顶部元素,返回front所在位置元素,front向前移。为了保证front可以从3移到1,front=(front+1)%elem.length

要点3:返回队列最后一个元素。如果rear=0,返回elem[elem.length-1].如果rear不为0,就返回elem[rear-1]

实现代码:

  1. class MyCircularQueue {
  2. private int[] elem;
  3. private int front;
  4. private int rear;
  5. public MyCircularQueue(int k) {
  6. elem = new int[k+1];
  7. }
  8. public boolean enQueue(int value) {
  9. if(isFull()){
  10. return false;
  11. }
  12. if(isEmpty()){
  13. elem[0] = value;
  14. front = 0;
  15. rear = 1;
  16. return true;
  17. }
  18. elem[rear] = value;
  19. rear = (rear+1) % elem.length;
  20. return true;
  21. }
  22. public boolean deQueue() {
  23. if(isEmpty()){
  24. return false;
  25. }
  26. front = (front+1) % elem.length;
  27. return true;
  28. }
  29. public int Front() {
  30. if(isEmpty()){
  31. return -1;
  32. }
  33. return elem[front];
  34. }
  35. public int Rear() {
  36. if(isEmpty()){
  37. return -1;
  38. }
  39. if(rear == 0){
  40. return elem[elem.length-1];
  41. }
  42. return elem[rear-1];
  43. }
  44. public boolean isEmpty() {
  45. return rear == front;
  46. }
  47. public boolean isFull() {
  48. if((rear+1)%elem.length == front){
  49. return true;
  50. }
  51. return false;
  52. }
  53. }

3.7 用队列实现栈

 OJ链接:225. 用队列实现栈 - 力扣(LeetCode)

解题思路:

要点1:有两个队列

要点2:第一次放push数据时,默认放到队列1中

要点3:添加元素时,添加到不为空的队列中,这样才能保证顺序

要点4:出栈—》获得栈顶元素—》栈后入先出—》弹出最后一个入栈的元素

因此,需要找出最后一个入队列的元素。将队列的前n-1个元素,放到另外一个队列中,剩下的就是最后一个入队列的元素

实现代码:

  1. class MyStack {
  2. private Queue<Integer> qu1;
  3. private Queue<Integer> qu2;
  4. public MyStack() {
  5. qu1 = new LinkedList<>();
  6. qu2 = new LinkedList<>();
  7. }
  8. public void push(int x) {
  9. // 如果队列2是空的,就往队列1里面放。原因:只有放在不为空的队列中顺序才不会乱
  10. if(qu2.isEmpty()){
  11. qu1.offer(x);
  12. }else{
  13. qu2.offer(x);
  14. }
  15. }
  16. public int pop() {
  17. if(empty()){
  18. return -1;
  19. }
  20. if(qu1.isEmpty()){
  21. // 队列2不为空,队列先进先出,将队列前size-1个元素放到队列1中,剩下的最后一个元素就是最后入队列的,也就是栈的第一个元素,将其返回
  22. int size = qu2.size();
  23. while(size > 1){
  24. qu1.offer(qu2.poll());
  25. size--;
  26. }
  27. int result = qu2.poll();
  28. return result;
  29. }
  30. if(qu2.isEmpty()){
  31. int size = qu1.size();
  32. while(size > 1){
  33. qu2.offer(qu1.poll());
  34. size--;
  35. }
  36. int result = qu1.poll();
  37. return result;
  38. }
  39. return -1;
  40. }
  41. public int top() {
  42. if(empty()){
  43. return -1;
  44. }
  45. if(qu1.isEmpty()){
  46. int size = qu2.size();
  47. while(size > 1){
  48. qu1.offer(qu2.poll());
  49. size--;
  50. }
  51. int result = qu2.poll();
  52. qu1.offer(result);
  53. return result;
  54. }
  55. if(qu2.isEmpty()){
  56. int size = qu1.size();
  57. while(size > 1){
  58. qu2.offer(qu1.poll());
  59. size--;
  60. }
  61. int result = qu1.poll();
  62. qu2.offer(result);
  63. return result;
  64. }
  65. return -1;
  66. }
  67. public boolean empty() {
  68. return qu1.isEmpty()&&qu2.isEmpty();
  69. }
  70. }

3.8 用栈实现队列

 OJ链接:232. 用栈实现队列 - 力扣(LeetCode)

 解题思路:

要点1:有两个栈。存数据都存到栈1中,取数据都从栈2中取。

要点2:取数据时,如果栈2是空的,就把栈1中的元素全放到栈2中。再从栈2中取。

实现代码:

  1. class MyQueue {
  2. private Stack<Integer> stack1;
  3. private Stack<Integer> stack2;
  4. public MyQueue() {
  5. stack1 = new Stack();
  6. stack2 = new Stack();
  7. }
  8. public void push(int x) {
  9. stack1.push(x);
  10. }
  11. public int pop() {
  12. if(empty()){
  13. return -1;
  14. }
  15. if(stack2.empty()){
  16. while(!stack1.empty()){
  17. stack2.push(stack1.pop());
  18. }
  19. }
  20. return stack2.pop();
  21. }
  22. public int peek() {
  23. if(empty()){
  24. return -1;
  25. }
  26. if(stack2.empty()){
  27. while(!stack1.empty()){
  28. stack2.push(stack1.pop());
  29. }
  30. }
  31. return stack2.peek();
  32. }
  33. public boolean empty() {
  34. return stack1.empty()&&stack2.empty();
  35. }
  36. }

3.9 最小栈

 OJ链接:155. 最小栈 - 力扣(LeetCode)

 解题思路:

要点1:创建两个栈。一个栈存放所有的元素,另外一个栈存放栈中最小的元素

要点2:第一次push数据,数据存放在两个栈中

要点3:之后存放数据,该数据小于等于最小栈的栈顶元素,才能存放到最小栈和stack中。否则,就只能存放到stack中

实现代码:

  1. class MinStack {
  2. public Stack<Integer> stack;
  3. public Stack<Integer> minStack;
  4. public MinStack() {
  5. stack = new Stack();
  6. minStack = new Stack();
  7. }
  8. public void push(int val) {
  9. // 如果第一次放元素,往stack和minStack里都放
  10. if(stack.empty() && minStack.empty()){
  11. stack.push(val);
  12. minStack.push(val);
  13. return;
  14. }
  15. // 如果存放的数据比minStack元素小,该元素同时放到两个栈中
  16. if(val <= minStack.peek()){
  17. stack.push(val);
  18. minStack.push(val);
  19. return;
  20. }else{
  21. // 否则,就只往stack中放
  22. stack.push(val);
  23. return;
  24. }
  25. }
  26. public void pop() {
  27. int peek = stack.pop();
  28. if(peek == minStack.peek()){
  29. minStack.pop();
  30. }
  31. }
  32. public int top() {
  33. if(stack.empty()){
  34. return -1;
  35. }
  36. return stack.peek();
  37. }
  38. public int getMin() {
  39. if(minStack.empty()){
  40. return -1;
  41. }
  42. return minStack.peek();
  43. }
  44. }


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/691257
推荐阅读
相关标签
  

闽ICP备14008679号