栈和队列经典题目刷题

71 阅读4分钟

1 有效括号

优先刷一遍,先用 java 来刷吧

image.png

使用 java 和栈进行模拟 思路, 首先使用 Stack 建立一个栈,使用 push 和 pop 进行操作 判断是否是奇数个,如果是返回错误 转换成字符串数组 对应字符进行遍历,如果左括号将其 push 进入栈中 否则判断是否为空 如果为空且非左括号返回 False

使用栈弹出一个字符,与判断当前字符和弹出字符是否互为左右括号 如果是继续,不是返回 false 最后通过 Stack 是否为空来进行说明

class Solution {

    public boolean isValid(String s) {

        Stack<Character> stack=new Stack<>();

        if(s.length()%2!=0){

            return false;

        }

        char[]s_array=s.toCharArray();

        for(int i=0;i<s_array.length;i++){

            char tmp=s_array[i];

            if(tmp=='{'||tmp=='('||tmp=='['){

                stack.push(tmp);

            }else{

                 //如果只有2个字符并且先出现右边字符,栈是空的

                if(stack.empty())

                return false;

                char s_top=stack.pop();

                if(tmp==')'&&s_top!='('){

                    return false;

  

                }

                if(tmp=='}'&&s_top!='{'){

                     return false;

  

                }

                if(tmp==']'&& s_top!='['){

                     return false;

                }

  

            }

  

        }

        return stack.empty();

  

    }

  

}

2 构建一个最小栈

image.png

思路:使用一个辅助栈来进行辅助,辅助栈只保存比当前栈顶元素小的元素进栈,

class MinStack {

    private Stack<Integer> stack;

    private Stack<Integer>MinStack;

    public MinStack() {

        stack=new Stack<>();

        MinStack=new Stack<>();//min stack存储降序元素,如果出现的值比minstack最小的小就push,

  

    }

    public void push(int val) {

        stack.push(val);

        if(MinStack.isEmpty()||val<=MinStack.peek()){

            MinStack.push(val);

        }

  

    }

    public void pop() {

        if(stack.pop().equals(MinStack.peek())){

            MinStack.pop();

        }

  

    }

    public int top() {

        return stack.peek();

  

    }

    public int getMin() {

        return MinStack.peek();

  

    }

}

  

/**

 * Your MinStack object will be instantiated and called as such:

 * MinStack obj = new MinStack();

 * obj.push(val);

 * obj.pop();

 * int param_3 = obj.top();

 * int param_4 = obj.getMin();

 */

3 用栈实现队列

这题也是经典的题目,面试手撕的常客

image.png

分析一波: 栈是先进后出,队列是先进先出

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false 栈 A 和栈 B Push: 将数据推入栈 A Peek:分类讨论:A 有数据,将 A 的数据依次 pop,然后 push 进入栈 B,最后栈 B 弹出。 B 有数据进行 peek A 无数据返回-1,因为为空栈 Pop:调用 peek,然后弹出栈 B 的开头元素,返回 peek 的值
class MyQueue {

    private Stack<Integer> A;

    private Stack<Integer>B;

  

    public MyQueue() {

        A=new Stack<>();

        B=new Stack<>();

    }

    public void push(int x) {

        A.push(x);

        //用栈实现队列

  

    }

    public int pop() {

        //将队首元素返回并且移除

        int peek=peek();

        B.pop();//栈b是进行将元素替换内容

        return peek;

  

    }

    public int peek() {//peek这个返回队首元素

    //栈B不为空

    if(!B.isEmpty()){

        return B.peek();

    }

    if( A.isEmpty()){

        return -1;//栈A为空的话说明没有数据

    }

    while(!A.isEmpty()){

        B.push(A.pop());

    }

    return B.peek();

  

    }

    public boolean empty() {

        return A.isEmpty()&&B.isEmpty();

  

    }

}

  

/**

 * Your MyQueue object will be instantiated and called as such:

 * MyQueue obj = new MyQueue();

 * obj.push(x);

 * int param_2 = obj.pop();

 * int param_3 = obj.peek();

 * boolean param_4 = obj.empty();

 */

4 LeetCode 394 字符串解码

image.png

这道题目通过辅助栈来进行运算

class Solution {

    public String decodeString(String s) {

        //通过解析[]来进行计算,当出现]将栈内元素全部弹出

        StringBuilder res=new StringBuilder();

        int multi=0;

        LinkedList<Integer> stackmulti=new LinkedList<>();//存储出现的数字次数

        LinkedList<String> stackres=new LinkedList<>();//存储出现的元素次数[前

        for(Character c:s.toCharArray()){

            if(c=='['){

                stackmulti.addLast(multi);//因为[前面一般是数字,multi已经处理好了

                stackres.addLast(res.toString());//接下来的数字后面可能是字母也已经处理好了

                multi=0;//重新将数字归0

                res=new StringBuilder();//重新建立空字符串

            }

            else if(c==']'){//遇到]将之前的数字和字母进行运算

                StringBuilder tmp=new StringBuilder();//创建一个

                int cur_multi=stackmulti.removeLast();

                for(int i=0;i<cur_multi;i++){

                    tmp.append(res);

                }

                res=new StringBuilder(stackres.removeLast()+tmp);//这一步将之前的保存在栈顶的元素和他们进行合并

            }

            else if(c>='0'&& c<='9')

            multi=multi*10+Integer.parseInt(c.toString());//这里是为了多位数字进行处理的方法

            else res.append(c);

        }

  
  

    return res.toString();

    }

}

思路,使用两个栈,对于字符串和数字进行分别存储,存储其数字和字符的内容 首先建立两个栈,一个字符串一个数字 定义初始的数字为 0

遍历字符: 如果字符是 0 到 9 之间,mulit=10*mult+Integer.pasetINt(c.toString () 如果普通字符 res 进行添加 如果是【进行处理,数字已经处理好了直接添加,因为也可能有字符串在数字前面 abc 3 这种,所以也进行添加

如果是】 弹出 multi 的数据,进行构建一个 Stringbuilder,multi 是几就对 数据 append 几次,最后返回的是字符串的栈顶元素来和组成的这个元素进行组装。

5 数据流的中位数

这道题的关键是两个堆的维护 堆 A 存储较大的元素的部分是小顶堆(默认就是小顶堆),元素个数比堆 B 要多 堆 B 存储较小的元素,是大顶堆,元素个数小于等于堆 A

image.png

class MedianFinder {

    Queue<Integer>A,B;

  

    public MedianFinder() {

        A=new PriorityQueue<>();// 小顶堆

        B=new PriorityQueue<>((x,y)->(y-x));

  
  

    }

    public void addNum(int num) {

        if(A.size()!=B.size()){

            A.add(num);//A保存较大的元素小顶堆,A的个数也比较多

            B.add(A.poll());

        }else{

            B.add(num);

            A.add(B.poll());//小元素的大顶堆这一步是为了包装A的数目小于B的数目使得数据满足上面的部分

        }

  
  

    }

    public double findMedian() {

       if (A.size()!=B.size()){

        return A.peek();//A是小顶堆存储较大的部分的数据

       }else{

        return (A.peek()+B.peek())/2.0;

       }

  
  

    }

}

  

/**

 * Your MedianFinder object will be instantiated and called as such:

 * MedianFinder obj = new MedianFinder();

 * obj.addNum(num);

 * double param_2 = obj.findMedian();

 */