代码随想录第11天 |栈与队列part02

本文介绍了如何借助栈实现有效括号验证、删除字符串重复项及逆波兰表达式求值,展示了栈在处理这些问题时的关键作用。

代码随想录算法训练营第11天 |栈与队列part02 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

题目一 20. 有效的括号

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

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。
    示例:
    输入: “([)]” 输出: false
    输入: “{[]}” 输出: true

首先进行分析:闭合正确的前提是,左右括号数量相等;
其次才是左右括号从内向外一一匹配。

同样,不匹配也就只有三种可能:左括号大于右,右括号大于左,左右匹配时种类不同。

方法就是:每匹配到一个左括号,就把它相对应的右括号压入栈中;
每读到一个右括号,如果栈顶和它相同,就挪出去。不相同则直接报错。
如果字符串没读完,栈已经空了,也同样报错。
直到最后看栈是否为空。

在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多.

import java.util.*;

class Solution {
    public boolean isValid(String s) 
    {
        int size = s.length();
        
        if(size % 2 != 0)
            return false;
            
        Deque<Character> newdeq = new LinkedList<>();
        for(int i=0; i<size; i++)
        {
            if( s.charAt(i) == '(' )
                newdeq.push( ')' );
            else if( s.charAt(i) == '[' )
                newdeq.push( ']' );
            else if( s.charAt(i) == '{' )
                newdeq.push( '}' );
                
            else if( newdeq.isEmpty() == true || newdeq.peek() != s.charAt(i) )
                return false;
            else newdeq.pop();
        }
        return newdeq.isEmpty();
    }
}

题目二 1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例: 输入:“abbaca” 输出:“ca”

本题关键是如何运用栈将重复元素不断扔出去。注意本题是反复的相邻消消乐,因此要考虑多次弹出的情况。
用栈来依次存放整个字符串,栈的目的就是存放遍历过的元素。
当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。如果不一样就放进来,如果相同的话把栈里的也弹出来。(这时候不用往栈里填了)然后再去做对应的消除操作。
从栈中弹出剩余元素,因为从栈里弹出的元素是倒序的,所以需要对字符串进行反转一下,得到最终的结果。
使用java时,直接让每次从栈中倒出来的元素加在空字符串前面即可,省去调用reverse()的麻烦。

import java.util.*;

class Solution {
    public String removeDuplicates(String s) 
    {
        Deque<Character> newstack = new LinkedList<>();
        int length = s.length();
        for(int i=0; i<length; i++)
        {
            char temp = s.charAt(i);
            if(newstack.isEmpty() == true || newstack.peek() != temp)
            {
                newstack.push( temp);
            }
            else{
                newstack.pop();
            }
        }
		//for(char ch : s)更简便
		
        String sb = "";
        while( newstack.isEmpty() != true)
        {   //注意加减的前后顺序
            sb = newstack.pop() + sb;
        }
        //reverse
        return sb;
    }
}

题目三 150. 逆波兰表达式求值

根据逆波兰表示法(即Lisp/Scheme语言的表达方式),求表达式的值。
有效的运算符包括 + , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:

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

逆波兰表示法在lisp/scheme语言中常见,具体的逻辑是构建一棵表达式树,将运算符置于上层节点,数字置于叶子节点,不同的表示法即是对树的不同层次遍历。当然,本题是可以用栈解决的。

只需每次将数字先置入栈中,读取到符号后就一并提出来运算,然后再放入栈中,重复此过程得到最终结果。

本题注意:
判断条件时,数字和运算符应当处于判断顺序的同一地位;对运算符处理之外的其他情况只剩下数字这一种情况。
以及申请栈空间使用的数据类型为数字即可。毕竟不用把运算符真的放进栈中,但数字需要。而且最后需要的是数字,不是字符串。
还有,减法和除法运算有数字的先后顺序,应当记住先后进栈出栈的数字谁应当在前面。
有关如何连续获取栈中两个数字,只需两次pop()即可。

import java.util.*;

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> newstack = new LinkedList<>();
        int len = tokens.length;
        for(String temp : tokens)
        {
            if( "+".equals(temp) )
            {
                newstack.push( newstack.pop() + newstack.pop() );
            }else if( "*".equals(temp) )
            {

                newstack.push( newstack.pop() * newstack.pop() );

            }else if( "-".equals(temp) )
            {
                newstack.push( - newstack.pop() + newstack.pop() );

            }else if( "/".equals(temp) )
            {
                int t1 = newstack.pop();
                int t2 = newstack.pop();
                newstack.push( t2 / t1);

            }else //only numbers
            {
                newstack.push( Integer.valueOf(temp) );
            }
        }
        return newstack.pop();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值