leetcode算法练习——20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值

leetcode算法练习

20. 有效的口号

题目链接
不匹配的场景:

  • ( [ { } ] () 左边括号多余
  • [ { ( } } ] 括号类型不匹配
  • [ { } ] ( ) ) ) 右边括号多余

思路:
剪支条件:如果数量不是偶数 可以直接判断无效

  1. 遇到左括号 就把对应的右括号加入到栈里 因为之后弹出匹配可以直接和元素进行比较
    例如:( [ { } ] () 就是先入栈) ] } 而后出栈和} ] 依次匹配 再将)入栈 最后因为)消除一个) 栈中还剩余一个) 说明是无效的
  2. 字符串的括号和栈中不匹配 说明是无效的
  3. 字符串还没有遍历完 栈就空了 说明右边括号多余了 是无效的
class Solution {
    public boolean isValid(String s) {
        Deque<Character> deque = new LinkedList<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            //碰到左括号,就把相应的右括号入栈
            if (ch == '(') {
                deque.push(')');
            }else if (ch == '{') {
                deque.push('}');
            }else if (ch == '[') {
                deque.push(']');
            } else if (deque.isEmpty() || deque.peek() != ch) {
                // 要先判断是否为空 否则取stack.peek是会异常的
                return false;
            }else {
                //如果是右括号判断是否和栈顶元素匹配
                deque.pop();
            }
        }
        // 第一种情况也处理了 当字符串遍历完 栈还为空 说明左括号是多的 是无效的
        // 如果栈为空 那么说明就是有效的
        return deque.isEmpty();
    }
}

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

题目链接
栈特别适用于相邻元素/重复项/括号匹配
思路:

  • 栈用来存放遍历过的元素 每遍历一个元素都要去栈中询问是否之前有遍历到过

例如:abbaca ——aaca——ca

  • a先入栈——栈内a
  • 遍历到b b和栈内a不相等 b入栈——栈内(栈顶)ba(栈底)
  • 遍历到b 发现栈顶为b 故把栈顶的b弹出——栈内a
  • 遍历到a 发现栈内a 故把栈顶的a弹出——栈为空
  • 遍历到c c存入栈中——栈为c
  • 遍历到a a和栈顶c不相同 存入栈中——栈为ac
  • 最后把栈内数据输出 转成字符串——可以直接用字符串来模拟栈 可以字符串的头部作为栈的尾部 字符串的尾部作为栈的头部 这样就可以不用反转了
class Solution {
    public String removeDuplicates(String S) {
        // ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char ch;
        // 循环遍历字符串
        for (int i = 0; i < S.length(); i++) {
            // 获取单个字母
            ch = S.charAt(i);
            // 如果栈为空或栈顶的元素和当前遍历的元素不同 直接存入
            if (deque.isEmpty() || deque.peek() != ch) {
                deque.push(ch);
            } else {
                // 弹出栈顶元素
                deque.pop();
            }
        }
        String str = "";
        // 剩余的元素即为不重复的元素
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }
}

150. 逆波兰表达式求值

题目链接
逆波兰表达式其实是一种后缀表达式
例如:(1+2)*(3+4)转换成二叉树 如图
二叉树
后序:12+34+×
中序:1+2×3+4(看着舒服 但是正确计算得加括号 (1+2)×(3+4))但后序表达式不需要——如何处理得到结果?利用栈

思路:

  • 遇到数字就加入栈 遇见操作符就从栈中取出数字 进行运算再存入栈中

例如:(1+2)*(3+4)转为12+34+×

  • 数字1 入栈——栈内1
  • 数字2 入栈——栈内(栈顶)2 1(栈底)
  • 操作符+ 取出2 1 运算得到3 再放入栈——栈内3
  • 数字3 入栈——栈内(栈顶)3 3(栈底)
  • 数字4 入栈——栈内(栈顶)4 3 3(栈底)
  • 操作符+ 取出4 3 运算得到7 再放入栈——栈内(栈顶)7 3(栈底)
  • 操作符× 取出7 3 运算得到21 再放入栈——栈内21(结果也放入栈 可以统一规则 免得再做特殊处理)
  • 结果就是21
class Solution {
    public int evalRPN(String[] tokens) {
        // 创建栈
        Deque<Integer> stack = new LinkedList();
        // 遍历字符串
        for (String s : tokens) {
            // 遇见操作符 去元素pop 存元素push
            if ("+".equals(s)) {        // leetcode 内置jdk的问题,不能使用==判断字符串是否相等
                stack.push(stack.pop() + stack.pop());      // 注意 - 和/ 需要特殊处理
            } else if ("-".equals(s)) {
                stack.push(-stack.pop() + stack.pop());
            } else if ("*".equals(s)) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(s)) {
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            } else {
                // 把数字放入栈中 要转为int类型
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值