算法刷题打卡009 | 栈应用题3道

今天复习利用栈与队列的特性解决问题。

LeetCode 20. 有效的括号

题目链接:20. 有效的括号 - 力扣(Leetcode)

有效的括号中,嵌套在最内层的右括号会与最近的左侧左括号匹配,根据栈后入先出的特性,可以把从左到右遍历到的左括号暂存到栈中,遇到右括号时检查栈顶是否与之匹配,栈为空或不匹配时整体括号无效,直接返回;括号匹配时将栈顶出栈,继续下一个括号的遍历。最后遍历结束,若栈不为空,存在多余的左括号,整体括号也是无效的。

class Solution:
    def isValid(self, s: str) -> bool:
        left, right = ['(', '[', '{'], [')', ']', '}']
        match = {')': '(', ']': '[', '}': '{'}
        stack = []
        for ch in s:
            if not stack and ch in right:
                return False  # 多了右括号
            if ch in left:
                stack.append(ch)
            else:
                if stack[-1] != match[ch]:  # 栈顶不是对应的左括号
                    return False  # 左右不匹配
                else:
                    stack.pop()
        return True if not stack else False  # 多了左括号

将两个if条件合并之后:

class Solution:
    def isValid(self, s: str) -> bool:
        match = {')': '(', ']': '[', '}': '{'}
        stack = []
        for ch in s:
            if ch in match:
                if not stack or stack[-1] != match[ch]:  # 栈为空或栈顶不是对应的左括号
                    return False  # 左右不匹配
                else:
                    stack.pop()
            else:
                stack.append(ch)
        return True if not stack else False  # 多了左括号

s中所有字符最多入栈出栈各一次,时间和空间复杂度都是O(n)。

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

题目链接:1047. 删除字符串中的所有相邻重复项 - 力扣(Leetcode)

这也是栈应用的一道经典题目了,利用栈暂存遍历到的字符,遇到字符与栈顶元素相同,即可出栈顶,相当于把一对相邻重复项删除了,栈为空或者字符与栈顶元素不相同则可以继续入栈。遍历结束后,栈中剩余元素即为返回结果。

class Solution:
    def removeDuplicates(self, s: str) -> str:
        n = len(s)
        if n == 1:
            return s
        # 用栈
        stack = []
        for i in range(n):
            if stack and s[i] == stack[-1]:
                stack.pop()  # 栈非空且当前字符与栈顶相同时, pop
            else:
                stack.append(s[i])
        
        ans = ''.join(stack)  # 栈最后剩下的字符就是最终的字符串
        return ans

同样的,时间和空间复杂度都是O(n)。

LeetCode 150. 逆波兰表达式求值

题目链接:150. 逆波兰表达式求值 - 力扣(Leetcode)

理解逆波兰表达式的原理之后,用栈很容易实现,但实际做的时候容易被python的整除//搞崩溃,因此debug了很久:

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for ch in tokens:
            if ch == '+':
                a, b = stack.pop(), stack.pop()
                stack.append(a + b)
            elif ch == '-':
                a, b = stack.pop(), stack.pop()
                stack.append(b - a)
            elif ch == '*':
                a, b = stack.pop(), stack.pop()
                stack.append(a * b)
            elif ch == '/':
                a, b = stack.pop(), stack.pop()
                if a * b < 0:
                    ans = - (abs(b) // abs(a))
                else:
                    ans = b // a
                stack.append(ans)
            else:
                stack.append(int(ch))  # 用ch.isdigit()会漏判负数
        return stack[0]

你可能感兴趣的:(刷题,算法,leetcode)