一、LeetCode20. 有效的括号
1:题目描述(20. 有效的括号)
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
2:解题思路
有三种不匹配的情况:
第一种:左括号没有匹配的右括号
第二种:左括号和右括号没有按顺序进行匹配
第三种:右括号多了,没有匹配的左括号
我们只需要将这三种情况处理掉就可以了。
下面描述的左括号为:(、{、[;右括号为:)、}、]
在本题,我们使用栈来解题,定义一个栈stack,遍历字符串,当碰到左括号 时,向栈中添加对应的右括号;当遍历到右括号时,就去与栈顶的元素对比,看两者是否相等,为同一型号的右括号,如果不是同一型号的括号,则说明没有按顺序进行匹配(即第二种情况);如果此时栈已经为空了,说明多了右括号(即第三种情况);如果相等,我们就把栈顶的元素弹出,继续遍历下一个元素;当元素遍历完了后,如果栈stack不为空,说明多了左括号(即第一种情况);栈为空了,说明字符串满足条件。
class Solution:
def isValid(self, s):
# 定义一个栈
stack = []
if len(s)%2 != 0: return False # 当字符串的长度为奇数时,一定有不匹配的括号
# 字符串的长度为偶数
# 遍历字符串
for i in range(len(s)):
# 当元素为“(”时,向栈中添加元素“)”
if s[i] == '(': stack.append(")")
# 当元素为“{”时,向栈中添加元素“}”
elif s[i] == '{': stack.append("}")
# 当元素为“[”时,向栈中添加元素“]”
elif s[i] == '[': stack.append("]")
# 当元素为右括号“)、}、]”时,去判断stack栈顶的元素是否为“)、}、]”
# 如果不相等,说明闭合的顺序不正确
# 如果栈已经为空了,说明没有与之匹配的左括号
elif len(stack) == 0 or s[i] != stack[-1]:
return False
# 如果相等,则括号是匹配的,将栈顶的元素弹出,继续遍历下一个元素
else:
stack.pop()
# 如果遍历完字符串,stack中还有元素,说明字符串中有左括号没有匹配的右括号
if len(stack) != 0: return False
# stack中没有元素了,说明括号都以正确的顺序进行闭合了
return True
可以将代码进行优化一下,我们可以将左括号对应的右括号存在一个字典中,遍历到左括号,就将左括号对应的右括号添加到栈stack中。
class Solution:
def isValid(self, s):
# 定义一个栈
stack = []
s_dict = {
"(":")",
"{":"}",
"[":"]"
}
if len(s)%2 != 0: return False # 当字符串的长度为奇数时,一定有不匹配的括号
# 字符串的长度为偶数
# 遍历字符串
for i in range(len(s)):
# 当元素为左括号时,向栈中添加对应的右括号
if s[i] in s_dict:
stack.append(s_dict[s[i]])
# 当元素为右括号“)、}、]”时,去判断stack栈顶的元素是否为“)、}、]”
# 如果不相等,说明闭合的顺序不正确
# 如果栈已经为空了,说明没有与之匹配的左括号
elif len(stack) == 0 or s[i] != stack[-1]:
return False
# 如果相等,则括号是匹配的,将栈顶的元素弹出,继续遍历下一个元素
else:
stack.pop()
# 如果遍历完字符串,stack中还有元素,说明字符串中有左括号没有匹配的右括号
if len(stack) != 0: return False
return True
二、LeetCode1047. 删除字符串中的所有相邻重复项
1:题目描述(1047. 删除字符串中的所有相邻重复项)
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
2:解题思路
使用栈来进行解题
定义一个栈stack,来存放我们遍历字符串的的元素,当元素与栈顶元素相等时,将栈顶元素弹出,当栈为空或者元素与栈顶元素不相等时,将元素加入到栈中。
class Solution:
def removeDuplicates(self, s):
stack = [] # 定义一个栈,用来存放遍历过的元素
for item in s:
if len(stack) == 0: # 当栈为空时,把元素加入到栈中
stack.append(item)
else: # 当栈不为空
if item == stack[-1]: # 当前元素与栈顶元素相等,则将栈顶元素弹出
stack.pop()
else: # 当前元素与栈顶元素不相等,则将元素加入栈
stack.append(item)
s = "".join(stack) # 将栈中的元素拼接成字符串
return s
三、LeetCode150. 逆波兰表达式求值
1:题目描述(150. 逆波兰表达式求值)
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意 两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
2:解题思路
先来看看什么是逆波兰表达式。
逆波兰表达式:是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
-
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
-
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
因此先定义一个栈stack,然后遍历tokens,如果遍历的元素是数字,则将数字加入到栈stack中,如果遍历的元素是“+、-、*、/”,则从栈顶依次取出两个元素,转换为int类型后分别赋值给nums1,nums2,然后对取出的两个元素按照遍历到的运算符进行运算,nums2+nums1,nums2-nums1,nums2*nums1,nums2/nums1;再将得到的运算结果添加到栈stack中,进入遍历下一个元素,直到遍历完tokens,此时stack中存放的是逆波兰表达式运算的结果,把stack中的元素弹出进行返回;当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换。
class Solution:
def evalRPN(self, tokens):
stack = [] # 定义一个栈,用来存放遍历tokens的元素,及运算结果
# 遍历tokens
for item in tokens:
# 当元素为“+、-、*、/”
if item == "+" or item == "-" or item == "*" or item == "/":
# 取出栈stack中的栈顶的两个元素,取出来的元素是字符串,需要进行转化
nums2 = int(stack.pop())
nums1 = int(stack.pop())
# 元素为+时,进行加法运算,再将运算的结果添加到栈stack中
if item == "+":
stack.append(nums1+nums2)
# 元素为-时,进行减法运算,再将运算的结果添加到栈stack中
elif item == "-":
stack.append(nums1-nums2)
# 元素为*时,进行乘法运算,再将运算的结果添加到栈stack中
elif item == "*":
stack.append(nums1*nums2)
# 元素为/时,进行除法运算,再将运算的结果添加到栈stack中
elif item == "/":
stack.append(nums1/nums2)
# 当元素为数字时,将元素加入到栈中
else:
stack.append(item)
# 遍历完tokens后,栈中存放的时逆波兰表达式的结果
# 当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换
res = int(stack.pop())
return res
使用eval()函数
class Solution:
def evalRPN(self, tokens):
stack = [] # 定义一个栈,用来存放遍历tokens的元素,及运算结果
tokens_set = {"+","-","*","/"}
# 遍历tokens
for item in tokens:
# 当元素为“+、-、*、/”
if item in tokens_set:
first_nums = stack.pop()
second_nums = stack.pop()
# 将nums1与nums1运算的结果,再添加到stack中
# 从栈stack中弹出的第一个元素,在运算符的后面
stack.append(int(eval(f'{second_nums} {item} {first_nums}')))
# 当元素为数字时,将元素加入到栈中
else:
stack.append(item)
# 遍历完tokens后,栈中存放的时逆波兰表达式的结果
# 当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换
res = int(stack.pop())
return res