算法训练营打卡Day11 | 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

一、LC20. 有效的括号

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

用栈来做。遍历字符串中的元素,左括号入栈,右括号和栈中最上面的元素比较,匹配的话继续比较,不匹配就返回false。需要考虑以下几种情况:

1. (){}

2.(]

3.] 或者()])   右括号出现的时候左括号还没入栈。 

4. (()  遍历过程中括号都匹配,但遍历结束时栈中还有未匹配的左括号。只有遍历结束栈中没有元素才是符合条件的字符串。

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new ArrayDeque<>(); 
        Map<Character, Character> map = new HashMap<>();
        map.put('(',')');
        map.put('[',']');
        map.put('{','}');

        for (int i = 0; i < s.length(); i++) {
            if (map.containsKey(s.charAt(i))) {
                stack.push(s.charAt(i));
            } else {
                if (stack.isEmpty() || map.get(stack.poll()) != s.charAt(i)) {
                    return false;
                }
            }
        }
        
        if (stack.isEmpty()) {
            return true;
        }
        return false;
    }
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

二、LC1047. 删除字符串中的所有相邻重复项

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

本题要删除相邻相同元素,相对于20. 有效的括号 (opens new window)来说其实也是匹配问题,20. 有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。

本题也是用栈来解决的经典题目。

那么栈里应该放的是什么元素呢?

我们在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,那么如何记录前面遍历过的元素呢?

所以就是用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。然后再去做对应的消除操作。

因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。

方法一:
class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> stack = new ArrayDeque<>();

        for (int i = 0; i < s.length(); i++) {
            if (!stack.isEmpty() && (s.charAt(i) == stack.peek())) {
                //stack不为空且当前元素等于stack中最后一个元素
                stack.poll();
            } else {
                //1. stack为空
                //2,当前元素不等于stack中最后一个元素
                stack.push(s.charAt(i));
            }
        }

        String result = "";
        while (!stack.isEmpty()) {
            result = stack.poll() + result;
        } 

        return result;
    }
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)
方法二:拿字符串直接作为栈,省去了栈还要转为字符串的操作。
class Solution {
    public String removeDuplicates(String s) {
        // 将 res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        // StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();
        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
            if (top >= 0 && res.charAt(top) == c) {
                res.deleteCharAt(top);
                top--;
            // 否则,将该字符 入栈,同时top++
            } else {
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

三、LC150. 逆波兰表达式求值

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

视频讲解:栈的最后表演! | LeetCode:150. 逆波兰表达式求值_哔哩哔哩_bilibili

代码随想录

逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。

该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

  • 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中

思路:遍历输入,遇到数字加入栈中,遇到运算符号将栈中最顶部的两个元素pop做运算,将结果放回栈中方便后续计算。

在java中,int是32位有符号数据类型,其变量需要32位内存

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

        for (int i = 0; i < tokens.length; i++) {
            if (tokens[i].equals("+")) {
                stack.push(stack.poll() + stack.poll());
            } else if (tokens[i].equals("-")) {
                stack.push(-stack.poll() + stack.poll());
            } else if (tokens[i].equals("*")) {
                stack.push(stack.poll() * stack.poll());
            } else if (tokens[i].equals("/")) {
                int tmp = stack.poll();
                stack.push(stack.poll()/tmp);
            } else {
                System.out.println(tokens[i]);
                stack.push(Integer.parseInt(tokens[i]));
            } 
        }

        return stack.pop();
    }
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值