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

20. 有效的括号

题目链接 | 解题思路

由于栈结构的特殊性,非常适合做对称匹配类的题目。只要能够明确匹配关系,就可以知道什么时候 push,什么时候 pop,可以很好利用栈的 LIFO 的特性。

自己的解法(略笨重)

符合直觉的思路,从后向前在 stack 中存入每个字符,如果存入的是前括号,则 pop 栈中的最后一个元素并检查是否是对应的后括号,不匹配则 return False。
最后如果 stack 不为空,则 return False,反之return True。

class Solution:
    def isValid(self, s: str) -> bool:
        str_stack = list(s)
        bracket_stack = []
        while (len(str_stack) > 0):
            curr_bracket = str_stack.pop()
            if curr_bracket in [')', ']', '}']:
                bracket_stack.append(curr_bracket)
            else:
                if len(bracket_stack) == 0:
                    return False
                else:
                    if curr_bracket == '(' and bracket_stack.pop() != ')':
                        return False
                    if curr_bracket == '[' and bracket_stack.pop() != ']':
                        return False
                    if curr_bracket == '{' and bracket_stack.pop() != '}':
                        return False
        return len(bracket_stack) == 0

标准的栈解法

更加简洁一些的解法,从头开始遇到前括号则在 stack 中存入对应的后括号,遇到后括号则比较当前 stack 的 pop 元素是否匹配。

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)
class Solution:
    def isValid(self, s: str) -> bool:
        bracket_stack = []
        for letter in s:
            if letter == '(':
                bracket_stack.append(')')
            elif letter == '[':
                bracket_stack.append(']')
            elif letter == '{':
                bracket_stack.append('}')
            elif len(bracket_stack) == 0:           # the read letter must be a close bracket
                return False
            elif bracket_stack[-1] != letter:
                return False
            else:
                bracket_stack.pop()
        return len(bracket_stack) == 0

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

题目链接 | 解题思路

和上一题几乎一样,只是这次是匹配相邻元素,更加符合栈的特性。

class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack = []
        for letter in s:
            if len(stack) > 0:
                top_letter = stack.pop()
                if top_letter != letter:
                    stack.append(top_letter)
                    stack.append(letter)
            else:
                stack.append(letter)
        return "".join(stack)

150. 逆波兰表达式求值

题目链接 | 解题思路

逆波兰表达式是一种后缀表达式,即 operator 写在 operand 的后面。
例如:10 6 9 3 + -11 * / * 17 + 5 + = (10 * 6 / [(9+3) * (-11))]) + 17 + 5

逆波兰表达式很好的展现了计算机的计算方式,这和人类的计算思路是不一样的。
由于逆波兰表达式严格遵循从左到右的计算顺序,不需要括号以及优先级判断,所以非常适合使用栈来进行运算.

注意的是,在 / 的 case 中,int(operand2 / operand1) 的计算方式是“The division between two integers always truncates toward zero”。在结果为 negative float 的时候,是向0取整,和 // 的向下取整是不同的。

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for s in tokens:
            if s.isdigit() or (s[0] == '-' and len(s) > 1):
                stack.append(int(s))
            else:
                operand1 = stack.pop()
                operand2 = stack.pop()
                if s == '+':
                    stack.append(operand2 + operand1)
                if s == '-':
                    stack.append(operand2 - operand1)
                if s == '*':
                    stack.append(operand2 * operand1)
                if s == '/':
                    stack.append(int(operand2 / operand1))
        return stack[0]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值