问题描述
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
-
左括号必须用相同类型的右括号闭合。
-
左括号必须以正确的顺序闭合。
-
每个右括号都有一个对应的相同类型的左括号。
示例 1: 输入:s = "()" 输出:true 示例 2: 输入:s = "()[]{}" 输出:true 示例 3: 输入:s = "(]" 输出:false
思路
首先看了看问题,发现不考虑括号嵌套的情况,那么放心大胆地借鉴最长公共前缀的思路,看看[
的索引 +1
是不是]
。
class Solution:
def isValid(self, s: str) -> bool:
if '(' in s and ')' in s:
return s.find('(') + 1 == s.find(')')
elif '[' in s and ']' in s:
return s.find('[') + 1 == s.find(']')
elif '{' in s and '}' in s:
return s.find('{') + 1 == s.find('}')
else:
return False
这也太笨了
用时60ms,这里还是使用了str.find()
的方法,但是前提是要先判断某个括号在s
里面。
试一试提交,完蛋,错误。
输入s = "(){}}{"
,正确答案False,输出了True,原来是大括号重复出现了,
str.find()
方法只会返回第一个查找到的值的索引。emmmmm,看来要重新构思了。
好的没构思出来,问问chatgpt。
class Solution: def isValid(self, s: str) -> bool:
stack = []
for c in s:
if c in ['(', '{', '[']:
stack.append(c)
elif not stack or abs(ord(c) - ord(stack.pop())) > 2:
return False
return not stack
这里先创建一个栈stack
,对s
中每个元素进行遍历,假如找到一个左括号,就用append
方法将左括号压入栈中,接下来elif not stack or abs(ord(c)) - ord(stack.pop())) > 2
表示如果stack为空
or 不为空但c的ASCII值
- stack弹出字符的ASCII值
>2时,返回False
因为在 ASCII 编码中,‘(’、‘)’、‘{’、‘}’、‘[’ 和 ‘]’ 的数字值是连续的。例如,‘(’ 的 ASCII 值是 40,而 ‘)’ 的值是 41,它们之间的差为 1。同样,‘[’ 和 ‘]’ 之间的差为 2,‘{’ 和 ‘}’ 之间的差也为 2。
而栈的特性是后进先出
,试想一下:
- 我遇到一个
(
,好的,压入stack
。 - 再往
s
的右边遍历,到第二位括号,现在stack
肯定不为空嘛,从stack
中弹出了一个值,就是刚刚第一个括号,检查两者ASCII值之差的绝对值,大于2肯定不连续,也就不匹配,小于2时,好的,这一对括号匹配到了,到下一个循环。 - 那现在
stack
又空了,再遇到左括号压入栈中,遇到右括号再把左括号弹出。 - 如果先遇到右括号,就是
c
不在['(', '[', '{']
中,跳到elif
,但是stack
现在肯定是空的,直接False
。 - 假如全部匹配的话,
stack
肯定都弹完了,就return not stack
,如果空的,就True
,反之False
结果
用时40ms,内存16mb,击败51.72%和7.28%。
注意点和总结
stack.pop()
是从栈顶弹出元素,也就是上一个进去的。
ord()
方法能返回元素的ASCII值。