Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules:
- Any left parenthesis '(' must have a corresponding right parenthesis ')'.
- Any right parenthesis ')' must have a corresponding left parenthesis '('.
- Left parenthesis '(' must go before the corresponding right parenthesis ')'.
- '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string.
- An empty string is also valid.
Example 1:
Input: "()"
Output: True
Example 2:
Input: "(*)"
Output: True
Example 3:
Input: "(*))"
Output: True
Note:
- The string size will be in the range [1, 100].
这道题我最一开始就count了,结果发现顺序很重要,单纯的count不行。然后我转而用了另一个方法,就是建立一个array,读取一个char,如果是(和#,就先加入array,如果是)那么率先看看这个array最后一个(,把这个去掉(在这里我用了#替换),如果没有(,就找最后一个,当全部循环结束,再这个array从后往前读,看(能不能都被中和掉。
class Solution:
def checkValidString(self, s: str) -> bool:
if not s: return True
chars = []
for char in s:
if char == "(" or char == "*":
chars.append(char)
else:
index = self.find_last_element('(', chars)
if index != -1:
chars[index] = '#'
else:
index = self.find_last_element('*', chars)
if index != -1:
chars[index] = '#'
else:
return False
count = 0
for i in range(len(chars)-1, -1 , -1):
if chars[i] == '*':
count += 1
elif chars[i] == '(':
if count > 0:
count -= 1
else:
return False
return True
def find_last_element(self, char: str, chars: list) -> int:
for i in range(len(chars)-1, -1, -1):
if chars[i] == char:
return i
return -1
但其实这道题因为要找最后一个(或者, 并去掉。有一种数据结构正适合这个, 就是stack。可以建立两个stack,一个left储存(的index,一个star存的index,然后遇到)就先pop left的stack,如果为空了就pop star。如果两个都是空,就return false。如果最后两个有剩余,那么就看left pop的top是不是一直比star的小。时间复杂度是O(N), 空间复杂度是O(N)
class Solution:
def checkValidString(self, s: str) -> bool:
if not s: return True
left, star = [], []
for i in range(len(s)):
if s[i] == '(': left.append(i)
elif s[i] == '*': star.append(i)
else:
if not left and not star: return False
if left: left.pop()
else: star.pop()
while left and star:
if left[-1] > star[-1]: return False
left.pop()
star.pop()
return not left
还有一种解法是我在网上看到的,算是贪心吧。就是用两个值,low和high,low记录如果所有的*都是右括号,左括号的最少值。high记录如果所有的星都是左括号,左括号最多可以有的值。如果low大于0,就说明左括号太多,就算把所有的星都算是右括号也不够中和,如果high小于零,就说明右括号太多,把所有的星都算成是左括号也不够。当我们读取一个数是左括号的时候,low和high都加一,如果读取的是一个右括号,如果low大于0,就减一,high减一,如果读到的是星,那么如果low大于0,low就减一,high就加一。如果这个时候high是小于零的就是false。最后判断low是不是为0。这样做时间复杂度是O(N), 空间复杂度是O(1).
class Solution:
def checkValidString(self, s: str) -> bool:
low, high = 0, 0
for char in s:
if char == '(':
low += 1
high += 1
elif char == ')':
if low > 0: low -= 1
high -= 1
else:
if low > 0: low -= 1
high += 1
if high < 0: return False
return low == 0