栈与对列——20. 有效的括号;1047. 删除字符串中的所有相邻重复项 ;150. 逆波兰表达式求值
文档链接:代码随想录
做题感悟:
- 有效括号的判断:注意遍历字符串的同时,使用栈辅助,左括号对应的右括号放入,遇到匹配的右括号则pop,若左右括号多余,或括号不匹配,则返回False
- 利用栈来保存字符串的不重复的元素,实现在遍历字符串的同时更新并删除重复的两个元素,真的很妙。
- 利用栈实现运算的优先级操作,先把数字放进去,遇到运算符后,对前两个字符串进行操作,并放入栈内。直到遇到下一个运算符,由此实现运算的优先级。
题目一:20. 有效的括号——40min
利用栈实现左右括号的匹配。
匹配后将括号pop
注意,存在左括号多余、右括号多余、左右括号不匹配的情况。
class Solution:
def isValid(self, s: str) -> bool:
# 有效括号的匹配,主要是括号类型,左右括号的匹配
# 如果左右括号多出,或类型不符,都不是有效的括号,为此需要分别做左右匹配的判断以及类型的判断
# 使用栈,如果是左括号就放入栈中,直到找到匹配的右括号。
# 最后栈为空(说明左括号不多余),
# 若在遍历过程中,发现栈为空,说明右括号多余。
stack = []
str = list(s)
P = 0
for item in str:
if item == '(': # 如果是左括号,则在栈内放入右括号
stack.append(')')
elif item == '{':
stack.append('}')
elif item == '[':
stack.append(']')
elif not stack or stack[-1] != item: # 如果不是对应的右括号,或者是栈空
return False
else: # 如果是匹配的右括号,则弹出改右括号
stack.pop()
if not stack: # 如果栈是空的
return True # stack为空说明左括号均找到匹配
else:
return False # 如果不为空,说明左括号多余
题目二:1047. 删除字符串中的所有相邻重复项 ——23min
- 相邻的重复项是两个相邻,类似于连连看,相同的两个就消掉。
- 利用栈进行访问和更新字符串元素的状态,真的很妙。
class Solution:
def removeDuplicates(self, s: str) -> str:
# 类似于消消乐
# 不重复的元素放入栈内
# 遇到重复的元素就将栈内地元素以及重复的元素删除
# 最后输出字符串
s=list(s)
ans = [] # 初始化一个列表,用来做栈
for i in s:
# print(ans)
if ans and ans[-1] == i:# 如果非空则可以访问并pop
ans.pop()
else:
ans.append(i)
return ''.join(ans)
题目三:150. 逆波兰表达式求值 ——50min
- 逆波兰表达式,其实是左右中的遍历方式,遍历表达式。
- 计算机习惯顺序阅读表达式,因此使用逆波兰表达式。
- 其中,一个运算符的操作对象总是两个数字,因此先把数字放入栈内,遇到运算符再对栈内的前两个数字进行处理,并放回,就可以实现运算的优先级。
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
# 顺序遍历数组
# 遇到数字就放入栈中,
# 遇到字符就取出数字,按照字符规律进行运算,再放入栈内
ans = []
for i in tokens:
# print(i)
if i != '-' and i != '+' and i != '/' and i != '*':
# 如果是数字
ans.append(int(i))
#print(ans)
#print(i)
else:
if i == '-':
b=ans.pop()
a=ans.pop()
ans.append(a-b)
elif i == '+':
b=ans.pop()
a=ans.pop()
ans.append(a+b)
elif i == '/':
b=ans.pop()
a=ans.pop()
ans.append(int(a/b))
# int()是向下取整
# ceil()是向上取整
# round()是四舍五入
elif i == '*':
b=ans.pop()
a=ans.pop()
ans.append(a*b)
print(ans)
return ans[0] # 取整