• 【数据结构】栈和队列面试题总结(持续更新中...)


    目录

    一、栈相关基础概念

    二、队列相关基础概念

    三、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 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 stack = new Stack<>();
    4. for(int i = 0 ;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 stack = new Stack<>();
    4. HashSet 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 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 stack1 = new Stack();
    6. int pos = 0;
    7. for(int i=0;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 qu1;
    3. private Queue 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 stack1;
    3. private Stack 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 stack;
    3. public Stack 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. }


     

  • 相关阅读:
    Minillama3->训练tokenizer
    hadoop 实现数据排序
    软考高项-成本管理
    在uni-app中使用手机号一键登录
    前端开发---在vue项目中使用openLayers
    apollo源码解读:/cyber/sysmo 模块
    【Python】按特定条件查找列表的最小/最大值
    AN基础工具——动画人物上色
    笔试题之指针结合数组的精讲2
    作战仿真试验理论体系研究
  • 原文地址:https://blog.csdn.net/weixin_44258092/article/details/126240946