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

Day10

20. 有效的括号


力扣题目链接

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

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。

  • 左括号必须以正确的顺序闭合。

  • 注意空字符串可被认为是有效字符串。

思路

  • 这种处理对称性的问题,可以使用栈来解决

  • 不符合题意有三种情况:左括号多,右括号多,左右括号不匹配

  • 每次加入的元素有几种情况:

  • 如果是左括号,就直接加入对应的右括号即可

  • 如果是右括号,这时候按道理应该从栈中pop元素,但如果这时候栈空(右括号多),直接返回false

  • 栈不空,就比较栈peek的元素和待比较的右括号是否相等,不等直接返回false

  • 相等,就pop元素,进行下一次循环

  • 循环结束之后,由于可能左括号多,也就是这时候栈非空,也返回false

  • 时间复杂度O(n) 遍历一遍字符串

  • 空间复杂度O(n) 使用栈的辅助空间

代码

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                stack.push(')');
                continue;
            }
            if (s.charAt(i) == '[') {
                stack.push(']');
                continue;
            }
            if (s.charAt(i) == '{') {
                stack.push('}');
                continue;
            }
            if (stack.isEmpty() || stack.pop() != s.charAt(i)) {//防止右括号多和左右括号不匹配
                return false;
            }
        }
        return stack.isEmpty();//防止左括号多
    }
}
  • 注意:char类型不是对象,直接写入泛型的数据类型中是错误的,需要使用它的包装类Character

  • 题外话:

  • 为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?

  • 问题就在于List有多个实现类,如 LinkedList或者Vector等等,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类呢?

  • 这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。

  • 假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了 ArrayList特有的方法和属性。 ,如果没有特别需求的话,最好使用List list = new LinkedList(); ,便于程序代码的重构. 这就是面向接口编程的好处

  • list只能使用ArrayList中已经实现了的List接口中的方法,ArrayList中那些自己的、没有在List接口定义的方法是不可以被访问到的

  • list.add()其实是List接口的方法,但是调用ArrayList的方法如 clone()方法是调用不到的

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


力扣题目链接

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

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

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

思路

  • 使用栈很快

  • 对每个元素,如果栈非空且与栈顶元素匹配,那么将栈顶元素直接弹出

  • 否则,可能栈空或者不匹配,就把这个元素入栈

  • 遍历结束之后,栈内的元素就是剩下的,把它们依次pop出

  • 注意,如果用StringBuilder接收,需要再翻转一下

代码

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            if (!stack.isEmpty() && stack.peek() == s.charAt(i))
                stack.pop();
            else
                stack.push(s.charAt(i));
        }
        StringBuilder builder = new StringBuilder();
        while (!stack.isEmpty())
            builder.append(stack.pop());
        return new String(builder.reverse());
    }
}

150. 逆波兰表达式求值


力扣题目链接

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

思路

  • 逆波兰表达式求值是典型的使用栈处理的问题

  • 遍历数组,遇到数字直接进栈

  • 遇到符号,把栈顶的两个元素运算(后pop出的对先pop出的运算),之后再入栈

  • 最后栈内只有一个元素,出栈即可

代码

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new ArrayDeque<>();

        for (int i = 0; i < tokens.length; i++) {
            String cur = tokens[i];
            if ("+".equals(cur)) {
                stack.push(stack.pop() + stack.pop());
            } else if ("-".equals(cur)) {
                int temp = stack.pop();
                stack.push(stack.pop() - temp);
            } else if ("*".equals(cur)) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(cur)) {
                int temp = stack.pop();
                stack.push(stack.pop() / temp);//注意减法和除法的特殊处理
            } else {
                stack.push(Integer.valueOf(cur));
            }
        }
        return stack.pop();
    }
}

总结

今天的几个题目都是栈的应用,当看到对称问题的时候可以使用栈处理

有效的括号:如果是左括号,加入对应的右括号,这样比较起来方便,返回false有三种情况:要么不匹配,要么左括号多,要么右括号多,分别进行考虑

删除相邻重复项:还是栈的原理,保证栈非空前提下,每次看看栈顶元素和要加入的是否一样,一样就pop出,不一样或者空就加入这个元素

逆波兰表达式求值:遍历字符串数组,如果是数字直接入栈,如果是符号,要从栈中pop两个元素,后pop出的对先pop出的做运算,将结果再入栈即可

加油!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值