题目描述:
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-parentheses
解题思路
1. 利用计数的方法统计是否左右括号的数量是否匹配
设定int型变量 left、right,统计左右括号的数量,判断其是否相等(方法很笨)
另外一种是设定一个int变量称之为left,初始值为0。
遍历整个字符串,出现一个左括号则变量+1,出现一个右括号则变量-1,最后left变量为0则说明左右括号数量相等,反之亦然。
分析:第二个思路有效统计了左右括号的数量关系,但是没有考虑到位置逻辑关系,仍无法解决问题,参考示例4。
既要考虑数量关系,又要考虑逻辑关系,应该怎么做?
2. 利用栈的方法,FILO先进后出的特性
给定一个栈,遍历整个字符串。
若为左括号则push进入栈中;若为右括号则pop出栈顶的符号,判断其是否为同类型的左括号。
若匹配则进行下一个字符的判断,若不匹配则将右括号push进栈。
遍历整个字符串,若栈为空则字符串有效,若栈非空则字符串无效。
复杂度分析:
时间复杂度:O(n)
,因为我们一次只遍历给定的字符串中的一个字符并在栈上进行 O(1)
的推入和弹出操作。
空间复杂度:O(n)
,当我们将所有的开括号都推到栈上时以及在最糟糕的情况下,我们最终要把所有括号推到栈上。例如 ((((((((((
。
该方法的代码:
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
stack = []
mapping = {')':'(','}':'{',']':'['}
for chars in s:
if chars in mapping.values():
stack.append(chars)
if chars in mapping.keys():
top_element = stack.pop() if stack else 'a'
if mapping[chars] != top_element:
return False
return not stack
3.循环消消乐
在乐扣此题评论下有一个很有意思的写法。代码非常的简洁,眼前一亮。
主要思路很简单,通过循环不断消除字符串中的 ()
,[]
,{}
的字符串。如果字符串是合法的,那么最终消除完的字符串必是一个空串,如果字符串非法则最终的字符串非空。
代码如下:
class Solution:
def isValid(self, s):
while '{}' in s or '()' in s or '[]' in s:
s = s.replace('{}', '')
s = s.replace('[]', '')
s = s.replace('()', '')
return s == ''
复杂度分析:
时间复杂度:O(n 2 ),在每次循环语句的判断中,都要进行时间复杂度为O(n)的一次查找,查找字符串中是否有以上三个字符串。在合法字符串的情况下的该循环一共执行 n/2 次,故其时间复杂度较高。
空间复杂度:O(1),代码中没有申请额外的变量空间