栈和队列初步刷题篇

本文探讨了如何使用栈和队列解决算法问题,包括如何用两个栈实现队列,队列实现栈的方法,有效括号问题的解决方案,删除字符所有相邻重复项的策略,以及根据逆波兰表达式求值的算法。通过实例解析,阐述了栈和队列在这些经典问题中的应用。
摘要由CSDN通过智能技术生成

两个栈实现队列

方法:
两种倒入方法

class MyQueue {
    Stack<Integer>  stackIn ;
    Stack<Integer> stackOut ;

    public MyQueue() {
        stackIn=new Stack<>();
        stackOut=new Stack<>();    
    }

    public void InToOut(){
        while(!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
        }
    }
    //弹完一个后,不想弹了,重新入In
    public void outToIn(){
        while(!stackOut.isEmpty()){
            stackIn.push(stackOut.pop());
        }
    }
    
    public void push(int x) {
        //每次弹完我都会重新弹回来
        stackIn.push(x);
    }
    
    public int pop() {  
        InToOut();
        int result= stackOut.pop();
        outToIn();
        return result;
    }
    
    public int peek() {
        InToOut();
        int result= stackOut.peek();
        outToIn();
        return result;
    }
    
    public boolean empty() {
        return stackOut.isEmpty()&&stackIn.isEmpty();
    }
}






class MyQueue {
    Stack<Integer>  stackIn ;
    Stack<Integer> stackOut ;

    public MyQueue() {
        stackIn=new Stack<>();
        stackOut=new Stack<>();    
    }

    public void InToOut(){
        //弹之前的操作,我有元素,我不需要你倒入;我没有元素才需要你倒入
        if(!stackOut.isEmpty()) return;
        while(!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
        }
    }
    
    public void push(int x) {
        stackIn.push(x);
    }
    
    public int pop() {  
        InToOut();
        return stackOut.pop();
    }
    
    public int peek() {
        InToOut();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackOut.isEmpty()&&stackIn.isEmpty();
    }
}

队列实现栈

方法:
一个队列
两个队列

class MyStack {
    Queue<Integer> que;
    Queue<Integer> help;
    public MyStack() {
        que=new LinkedList<>();
        help=new LinkedList<>();
    }
    
    public void push(int x) {
        que.add(x);
    }
    
    public int pop() {
        int size= que.size();
        size--;
        while(size-->0){
            help.add(que.poll());
        }
       int result=que.poll();
       Queue<Integer> temp=que;
       que=help;
       help=temp;
       return result;
    }
    
    public int top() {
        int size= que.size();
        size--;
        while(size-->0){
            help.add(que.poll());
        }
       int result=que.peek();
       //peek的还要压回去才可以交换队列
       help.add(que.poll());
       Queue<Integer> temp=que;
       que=help;
       help=temp;
       return result;
    }
    
    public boolean empty() {
        return que.isEmpty();
    }
}







class MyStack {
    Queue<Integer> que;
    public MyStack() {
        que=new LinkedList<>();
    }
    
    public void push(int x) {
        que.add(x);
    }
    
    public int pop() {
        int size= que.size();
        size--;
        while(size-->0){
            que.add(que.poll());
        }
        //把最后一个弹出
        int result=que.poll();
        return result;
    }
    
    public int top() {
        int size= que.size();
        size--;
        while(size-->0){
            que.add(que.poll());
        }
       int result=que.peek();
       que.add(que.poll());
       return result;
    }
    
    public boolean empty() {
        return que.isEmpty();
    }
}

有效括号问题

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。``

方法:
利用栈

class Solution {
    public boolean isValid(String s) {
        //遍历字符串,左括号就压入右括号,到了右括号,判断是否和peek一样,不一样就false,一样就把之前比较的peek弹出
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='('){
                stack.push(')');
            }else if(s.charAt(i)=='{'){
                stack.push('}');
            }else if(s.charAt(i)=='['){
                stack.push(']');
            }else if(stack.isEmpty()||stack.peek()!=s.charAt(i)){//如果不匹配
                return false;
            }else{//匹配
                 stack.pop();
            }
        }
        //比对正确
        return stack.isEmpty();
    }
}

删除字符所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:“abbaca”
输出:“ca”
解释:例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。

方法:
利用栈来找到相邻过程相邻

class Solution {
    public String removeDuplicates(String s) {
        //借助栈(刚刚好实现相邻):相邻就弹出,不相邻就压入,最后弹出拼接
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<s.length();i++){
            if(stack.isEmpty()) stack.push(s.charAt(i));
            else if(s.charAt(i)==stack.peek()) stack.pop();
            else stack.push(s.charAt(i));
        }
        char[] arr=new char[stack.size()];
        for(int i=arr.length-1;i>=0;i--){
            arr[i]=stack.pop();
        }
        return new String(arr);
    }
}

根据逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。

有效的运算符包括 + , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

输入: [“2”, “1”, “+”, “3”, " * "]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

方法:
和删除重复项一样,只是不是比对了,而是运算

PS:leetcode上内置的jdk不能用'=='判断字符串相等问题
class Solution {
    public int evalRPN(String[] tokens) {
        //遍历数组,数字直接入栈,操作符就取两个数操作结果入栈
        //这里的数和操作符都是字符串,转化压入
        Stack<Integer> stack=new Stack<>();
        for(int i=0;i<tokens.length;i++){
            if(tokens[i].equals("+")){//只有减和除才需要注意顺序
                stack.push(stack.pop()+stack.pop());
            }else if(tokens[i].equals("*")){
                stack.push(stack.pop()*stack.pop());
            }else if(tokens[i].equals("-")){
                stack.push(-stack.pop()+stack.pop());
            }else if(tokens[i].equals("/")){
                int num2=stack.pop();
                int num1=stack.pop();
                stack.push(num1/num2);
            }else{
                //压入数字
                stack.push(Integer.valueOf(tokens[i]));
            }
        }
        return stack.pop();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赑屃爱Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值