20. 有效的括号
确保每个左括号都能找到一个相对应的右括号,并且括号的顺序是正确的。
当遍历到左括号,就向栈压入对应右括号,
当遍历到右括号,就从栈顶弹出对应右括号,
如果栈顶右括号和遍历的右括号不同,则说明为无效括号,
如果遍历结束前,栈为空,则说明为无效括号。
class Solution:
def isValid(self, s: str) -> bool:
stack = []
for bracket in s:
# 若遇到左括号,则将对应右括号压入栈
if bracket == '(':
stack.append(')')
elif bracket == '{':
stack.append('}')
elif bracket == '[':
stack.append(']')
# 若遇到右括号,则将栈顶右括号推出
# 若stack为空,或者与栈顶右括号不匹配,则括号无效
elif not stack or stack[-1] != bracket:
return False
else:
stack.pop()
# 当字符串遍历完成,stack应该为空
return not stack
1047. 删除字符串中的所有相邻重复项
本题与上一题使用相同的思路,借助栈可以实现看似难以处理的操作。
class Solution:
def removeDuplicates(self, s: str) -> str:
stack = []
for char in s:
# 如果 stack 不为空,且栈顶元素和遍历元素相同,则弹出栈顶元素
if stack and stack[-1] == char:
stack.pop()
# 否则,遍历元素入栈
else:
stack.append(char)
return ''.join(stack)
150. 逆波兰表达式求值
什么是逆波兰表达式?这里引用代码随想录中的解释:
"
我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。
例如:4 + 13 / 5,这就是中缀表达式,计算机从左到右去扫描的话,扫到13,还要判断13后面是什么运算符,还要比较一下优先级,然后13还和后面的5做运算,做完运算之后,还要向前回退到 4 的位置,继续做加法,你说麻不麻烦!
那么将中缀表达式,转化为后缀表达式之后:["4", "13", "5", "/", "+"] ,就不一样了,计算机可以利用栈来顺序处理,不需要考虑优先级了。也不用回退了, 所以后缀表达式对计算机来说是非常友好的。
可以说本题不仅仅是一道好题,也展现出计算机的思考方式。
在1970年代和1980年代,惠普在其所有台式和手持式计算器中都使用了RPN(后缀表达式),直到2020年代仍在某些模型中使用了RPN。
参考维基百科如下:
During the 1970s and 1980s, Hewlett-Packard used RPN in all of their desktop and hand-held calculators, and continued to use it in some models into the 2020s.
"
如一下动画所示,如果遇到数字,直接入栈,如果遇到运算符,则取出栈顶2个数字进行运算。特别注意,最先出栈的数字是右操作数。
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for token in tokens:
# 如果遇到运算符,则需要弹出栈顶两个数字以进行运算
if token in {'+', '-', '*', '/'}:
# 需要注意的是,先弹出的数字是右操作数
right = stack.pop()
left = stack.pop()
if token == '+':
stack.append(left + right)
elif token == '-':
stack.append(left - right)
elif token == '*':
stack.append(left * right)
elif token == '/':
stack.append(int(left / right))
# 如果遇到数字,则直接入栈
else:
stack.append(int(token))
return stack.pop()