[LeetCode] 678. Valid Parenthesis String

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

猜你喜欢

转载自www.cnblogs.com/codingEskimo/p/12717938.html
今日推荐