括号匹配,栈实现队列,队列实现栈以及循环队列

1.括号匹配问题OJ

思路

  1. 利用栈的先进后出特性
  2. 左括号入栈
  3. 遇到右括号,这是就应该开始一一对比
  4. 不相等的情况无非是括号不匹配, 左括号多,右括号多
  5. 三种情况全部排查完毕之后则说明括号完全匹配
private static boolean isValid(String str) {
    
    
        if (str.length() == 0 || str.length() % 2 != 0) {
    
    
            return false;
        } else if (str == null) {
    
    
            return false;
        } else {
    
    
            Stack<Character> stack = new Stack<>();
            /*
            不匹配的三种可能
             1. 左括号多,字符串为空
             2. 栈空, 字符串多
             3. 上来就不匹配

             遍历字符串,左括号入栈,右括号和栈顶元素比较
             */
            for (int i = 0; i < str.length(); i++) {
    
    
                char ch = str.charAt(i);
                if (ch == '{' || ch == '[' || ch == '(') {
    
    
                    stack.push(ch);
                } else{
    
    // 遇到右括号
                    // 栈为空
                    if (stack.empty()) {
    
    // 【右括号多】
                        return false;
                    } else {
    
    
                        // 栈不为空
                        char tmp = stack.peek();
                        if (tmp == '{' && ch == '}' || tmp == '[' && ch == ']' || tmp == '(' && ch == ')'){
    
    
                            stack.pop();// 相等就弹出
                        }else{
    
    
                            return false;// 左右括号不匹配
                        }
                    }
                }
            }
            if (!stack.empty()){
    
    
                return false;// 左括号多
            }
            return true;
        }
    }

2.用队列实现栈OJ

思路

  1. 利用两个队列,只需要让不为空的进出队列即可
  2. 如果两个队列都不为空,则让其中某一个队列存储元素
  3. peekpop 操作记得控制好 这一边界条件
public class MyStack {
    
    
    public Queue<Integer> qu1 = new LinkedList<>();
    public Queue<Integer> qu2 = new LinkedList<>();

    /**
     * 入栈
     * 哪个不为空,哪个就存储
     * 如果都不为空,就制定其中一个存储即可
     * @param x 值
     */
    public void push(int x) {
    
    
        if (!qu1.isEmpty()) {
    
    
            qu1.offer(x);
        } else if (!qu2.isEmpty()) {
    
    
            qu2.offer(x);
        } else {
    
    
            qu1.offer(x);
        }
    }

    /**
     * 出栈
     * 先弹出 size - 1 个元素,每次均保留下来弹出的元素并让另一个队列存储
     * 最后再弹出剩余的那个元素,也就是队列最后一个元素【队列最后一个元素进入】就达到栈的的先进后出的功能
     * @return
     */
    public int pop() {
    
    
        if (empty()) {
    
    
            return -1;
        }
        int e = -1;
        if (!qu1.isEmpty()) {
    
    
            int sz = qu1.size() - 1;
            while (sz-- != 0) {
    
    
                e = qu1.poll();
                qu2.offer(e);
            }
            e = qu1.poll();
        } else {
    
    
            int sz = qu2.size() - 1;
            while (sz-- != 0) {
    
    
                e = qu2.poll();
                qu1.offer(e);
            }
            e = qu2.poll();
        }
        return e;
    }

    /**
     * 得栈顶元素不删除
     * 需要弹出 size 个元素并记录保留,作为入另一个队列元素和返回值
     * @return
     */
    public int top() {
    
    
        if (empty()){
    
    
            return -1;
        }else{
    
    
            int e = -1;
            if (!qu1.isEmpty()){
    
    
                int sz = qu1.size();
                while(sz--!=0){
    
    
                    e = qu1.poll();
                    qu2.offer(e);
                }
            }else{
    
    
                int sz = qu1.size();
                while(sz--!=0){
    
    
                    e = qu1.poll();
                    qu2.offer(e);
                }
            }
            return e;
        }
    }

    public boolean empty() {
    
    
        return qu1.isEmpty() && qu2.isEmpty();
    }
}

在这里插入图片描述在这里插入图片描述

如图所示就是一次“出栈pop”操作

  1. ABCDEF 先入队列
  2. 把一个不为空的队列queue1元素 ABCDE 搬入到另一个队列queue2中
  3. queue1 再出队列,这样就实现了“先进后出【后进先出】”的功能

3.用栈实现队列OJ

两个指定的栈实现队列

只需要制定一个栈入一个栈出即可达到队列的先进先出效果

public class MyyQueue {
    
    
    Stack<Integer> stack1 = new Stack<>();
    Stack<Integer> stack2 = new Stack<>();
    public void push(int x){
    
    
        stack1.push(x);
    }
    public int pop(){
    
    
        if (empty()){
    
    
            return -1;
        }else {
    
    
            if (stack2.empty()){
    
    
                while (!stack1.empty()){
    
    // 把栈1出完全部存入栈2
                    stack2.push(stack1.pop());
                }
            }
            return stack2.pop();//弹出栈2栈顶元素
        }
    }
    public int peek(){
    
    
        if (empty()){
    
    
            return -1;
        }else {
    
    
            if (stack2.empty()){
    
    
                while (!stack1.empty()){
    
    
                    stack2.push(stack1.pop());
                }
            }
            return stack2.peek();
        }
    }
    public boolean empty(){
    
    
        return stack1.empty() && stack2.empty();
    }
}

在这里插入图片描述

4.实现一个最小栈OJ

设计两个栈

  1. 一个栈 stack存储所有元素, minStack只存储stack当前中小的元素,按次序存储
public class MinStack {
    
    
    Stack<Integer> stack = new Stack<>();
    Stack<Integer> minStack = new Stack<>();
    public void push(int val){
    
    
        stack.push(val);
        if (minStack.empty()){
    
    
            minStack.push(val);
        }else{
    
    
            if (minStack.peek() <= val){
    
    // 如果存储了两个比 minStack 栈顶还小的元素,当 stack 弹出栈中的元素刚好和 minStack 栈顶一样的时候两个都需要弹出,因此需要包含相同的最小值存入 minStack 中
                minStack.push(val);
            }
        }
    }

    public void pop(){
    
    
        if (stack.pop() == minStack.peek()){
    
    
            minStack.pop();// 不可以把 minStack 的元素忽略掉
        }
    }
    public int top(){
    
    
        return stack.peek();
    }

    public int getMin(){
    
    
        return minStack.peek();
    }
}

5. 设计循环队列OJ

循环队列的详细剖析请查看我之前博客内容

class MyCircularQueue {
    
    
    private int[] elem;
    private int front, rear;

    public MyCircularQueue(int k) {
    
    
        this.elem = new int[k+1];
    }


    /**
     * 入队列
     *
     * @param value 值
     * @return
     */
    public boolean enQueue(int value) {
    
    
        if ((this.rear + 1) % this.elem.length == this.front) {
    
    
            return false;//满了
        } else {
    
    
            this.elem[this.rear] = value;
            this.rear = (this.rear + 1) % this.elem.length;
            return true;
        }
    }

    /**
     * 出队列
     *
     * @return
     */
    public boolean deQueue() {
    
    
        if (this.front == this.rear) {
    
    
            return false;
        } else {
    
    
            int val = this.elem[this.front];
//            this.front = (this.front + 1) % this.elem.length;// 因为是循环,所以不能直接 front+1
            return true;
        }
    }

    /**
     * 取队头元素【相当于 peek 】
     *
     * @return
     */
    public int Front() {
    
    
        if (this.front == this.rear) {
    
    
            return -1;// leetcode 抛异常会认为是你的代码错误,所以不能抛异常
        } else {
    
    
            int val = this.elem[this.front];
            return val;
        }
    }

    /**
     * 取队尾元素
     * rear处于0位置则返回this.elem.length-1
     * 所以不能直接进行 -1 操作
     *
     * @return
     */
    public int Rear() {
    
    
        if (this.rear == this.front) {
    
    
            return -1;
        } else {
    
    
            if (this.rear == 0) {
    
    
                return this.elem[this.elem.length - 1];
            } else {
    
    
                return this.elem[this.rear - 1];
            }
        }
    }

    public boolean isEmpty() {
    
    
        return this.front == this.rear;
    }

    public boolean isFull() {
    
    
        return this.rear + 1 == this.front;
    }
}

Guess you like

Origin blog.csdn.net/weixin_45364220/article/details/120594936