题目
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1、左括号必须用相同类型的右括号闭合。
2、左括号必须以正确的顺序闭合。
3、每个右括号都有一个对应的相同类型的左括号。
示例1:
输入:s = "()" 输出:true
示例2:
输入:s = "()[]{}" 输出:true
示例3:
输入:s = "(]" 输出:false
提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
解题思路
法1:
首先应该注意到的是有效字符串的长度一定是偶数,所以当字符串长度为奇数时,直接返回False。
后续可借助 栈 来实现:
我们遍历给定的字符串s时,当我们遇到一个左括号时,在后续的遍历中我们将需要一个相同类型的右括号将其闭合。由于后遇到的左括号要先闭合,因此我们可以将这个左括号放入栈顶。
当遇到一个右括号时,我们需要将一个相同类型的左括号闭合,此时,我们可以取出栈顶的左括号来判断它们是否为相同类型的括号。如果不是相同的类型,或者栈中并没有左括号(为空),则字符串s无效,返回False。
因为第一个是右括号时,字符串肯定是无效的,所以下面列出当第一个为左括号的情况下(即指针指到第二个括号时,栈不为空)对字符串进行遍历、判断的过程:
在这里,为了快速判断括号的类型,我们可以借助字典进行,字典的键为左括号,值为相对应的右括号。
遍历结束后,如果栈中没有左括号,说明字符串中所有的左括号都完成了闭合,字符串s有效,返回True,否则返回False。
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
#首先判断字符串长度
if len(s) % 2 != 0 :
return False
#构造字典
dict = { "(" : ")" , "[" : "]" , "{" : "}" }
stack = []
#遍历字符串
for i in s:
if i in dict:
stack.append(i) #遇到左括号入栈
else:
if stack != [] and i == dict[stack[-1]]:
stack.pop() #遇到右括号,当栈非空,且当前括号与栈顶的左括号配对,即该左括号在字典中所对应的右括号一致时,出栈(消去该左括号)
else:
return False
#遍历结束,当栈空时,说明左括号全部配对完成
if stack == []:
return True
else:
return False
法2:
后面在评论区发现了一个执行更快、内存消耗更低的方法,以下是评论区大佬“代码随想录”的解题思路及代码:
由于栈结构的特殊性,非常适合做对称匹配类的题目。
首先要弄清楚,字符串里的括号不匹配有几种情况。
一些同学,在面试中看到这种题目上来就开始写代码,然后就越写越乱。
建议要写代码之前要分析好有哪几种不匹配的情况,如果不动手之前分析好,写出的代码也会有很多问题。
先来分析一下 这里有三种不匹配的情况,
- 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
- 第二种情况,括号没有多余,但是 括号的类型没有匹配上。
- 第三种情况,字符串里右方向的括号多余了,所以不匹配。
我们的代码只要覆盖了这三种不匹配的情况,就不会出问题,可以看出 动手之前分析好题目的重要性。
动画如下:
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
分析完之后,代码其实就比较好写了,
但还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!
#仅使用栈,更省空间
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
stack = []
for i in s:
if i == '(':
stack.append(')')
elif i == '[':
stack.append(']')
elif i == '{':
stack.append('}')
#遇到右括号,当栈为空或者当前右括号与栈顶的右括号不一样时,字符串无效
elif not stack or i != stack[-1]:
return False
#遇到右括号,栈不为空且当前右括号与栈顶的一样,匹配成功,将栈顶的右括号出栈
else:
stack.pop()
return True if not stack else False
小知识
在字典dict = { key:value }中,只能通过key作为索引来获取其对应的值。其它常见应用如下:
以下内容引自CSDN博主「目元」的原创文章,遵循CC 4.0 BY-SA版权协议,转载附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yaoyuanna/article/details/126009259
1、通过key来遍历字典:
my_dict = {
"小明":80,
"小强":90,
"小刚":100
}
#通过 for key in dict 可以获取字典中所有的键
for key in my_dict :
print(key,":",my_dict[key])
#输出结果
小明:80
小强:90
小刚:100
2、遍历key
my_dict = {
"小明":80,
"小强":90,
"小刚":100
}
#字典中自带keys()方法获取所有的key
keys = my_dict.keys()
for key in keys:
print(key)
#输出结果
小明
小强
小刚
3、遍历value值
my_dict = {
"小明":80,
"小强":90,
"小刚":100
}
#字典中自带values()方法获取所有的value
values = my_dict.values()
for value in values:
print(value)
#输出结果
80
90
100
4、遍历字典项
my_dict = {
"小明":80,
"小强":90,
"小刚":100
}
#字典中提供items()方法可以获取字典中的所有键值对
items = my_dict.items()
for item in items:
print(item)
#输出结果
("小明",80)
("小强",90)
("小刚",100)
5、通过字典项遍历key和value
my_dict = {
"小明":80,
"小强":90,
"小刚":100
}
for key,value in my_dict.items():
print(key,":",value)
#输出结果
小明:80
小强:90
小刚:100