20. 有效的括号
1)题目描述
2)思路分析
- 括号配对的算法应该使用栈。
- 左括号入栈,右括号执行匹配。
主体思路:首先需要一个字典来将左括号与右括号配对,即
key(左括号):value(右括号)
。遍历字符串,当遇到左括号时入栈,遇到右括号时则pop栈顶元素,并查字典,栈顶元素是否与有括号匹配,匹配则不做其他操作,继续执行;不匹配则算法结束,配对失败返回false。当遍历结束之后检查栈,空栈则匹配成功,返回true,否则返回false。
3)代码
class Solution:
def isValid(self, s: str) -> bool:
s_dict = {
"(": ")",
"{": "}",
"[": "]"
}
stack = []
for item in s:
if item in s_dict.keys():
stack.append(item)
else:
if not stack:
return False
top = stack.pop()
if item != s_dict[top]:
return False
return True if not stack else False
1047. 删除字符串中的所有相邻重复项
1)题目描述
2)思路分析
- 遍历元素与栈顶元素比较,相同则出栈,不同则入栈(消消乐)。
- 虽然思路上是采用栈,但是代码上选择了队列,这是为了方便后输出,最后输出的时候是从栈底往栈顶输出,而队列即能执行pop,也能执行popleft,因此选择了deque。
主体思路:遍历字符串,比较之前先检查栈是否为空,栈为空则直接push,栈非空则pop栈顶元素,与当前元素比较,相同则不执行其他操作,继续遍历;不同则将当前元素入栈,重复上述操作直至遍历结束。
3)代码
from collections import deque
class Solution:
def removeDuplicates(self, s: str) -> str:
s_queue = deque()
res = []
for item in s:
if not s_queue:
s_queue.append(item)
else:
top = s_queue.pop()
if item != top:
s_queue.append(top)
s_queue.append(item)
if s_queue:
for i in range(len(s_queue)):
res.append(s_queue.popleft())
return "".join(res)
else:
return ""
150. 逆波兰表达式求值
1)题目描述
2)思路分析
- 逆波兰表达式求值采用栈。
- 数字入栈,碰到运算符pop两次栈顶元素,并执行该运算符操作。
重难点/易错点——区分正整数(负整数)和符号
- Python中提供了函数
isdigit()
和isinstance()
函数可以区分是否是“数字”,但是会误判负数为“非数字”。- 因此采用直接判断是否是数字的方法有些复杂,换个思路,运算符只有4个,区分了运算符,剩下的就是数字。
- 具体来说,将四个运算符放在列表中便于查询,当列表元素没有出现在运算符列表中是则判定为数字,执行入栈;相反,当踹出现运算符时则pop两次栈顶元素执行操作。
- 需要注意的是,第一次pop的栈顶元素在运算是位于运算符后,第二次pop的栈顶元素位于运算符前。即
num2 = int(stack.pop()) num1 = int(stack.pop())
。
3)代码
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
operators = ["+", "-", "*", "/"]
for item in tokens:
# 数字可能包含负数 现有函数无法同时识别正整数和负整数
if item in operators:
num2 = int(stack.pop())
num1 = int(stack.pop())
if item == "+":
new_num = num1 + num2
if item == "-":
new_num = num1 - num2
if item == "*":
new_num = num1 * num2
if item == "/":
new_num = num1 / num2
stack.append(new_num)
else:
stack.append(item)
# 要求返回值为int类型
return int(stack.pop())