Skip to content

2116.判断一个括号字符串是否有效

stack, greedy, https://leetcode.cn/problems/check-if-a-parentheses-string-can-be-valid/

一个括号字符串是只由 '('')' 组成的 非空 字符串。如果一个字符串满足下面 任意 一个条件,那么它就是有效的:

  • 字符串为 ().
  • 它可以表示为 ABAB 连接),其中AB 都是有效括号字符串。
  • 它可以表示为 (A) ,其中 A 是一个有效括号字符串。

给你一个括号字符串 s 和一个字符串 locked ,两者长度都为 nlocked 是一个二进制字符串,只包含 '0''1' 。对于 locked每一个 下标 i

  • 如果 locked[i]'1' ,你 不能 改变 s[i]
  • 如果 locked[i]'0' ,你 可以s[i] 变为 '(' 或者 ')'

如果你可以将 s 变为有效括号字符串,请你返回 true ,否则返回 false

示例 1:

img

输入:s = "))()))", locked = "010100"
输出:true
解释:locked[1] == '1' 和 locked[3] == '1' ,所以我们无法改变 s[1] 或者 s[3] 。
我们可以将 s[0] 和 s[4] 变为 '(' ,不改变 s[2] 和 s[5] ,使 s 变为有效字符串。

示例 2:

输入:s = "()()", locked = "0000"
输出:true
解释:我们不需要做任何改变,因为 s 已经是有效字符串了。

示例 3:

输入:s = ")", locked = "0"
输出:false
解释:locked 允许改变 s[0] 。
但无论将 s[0] 变为 '(' 或者 ')' 都无法使 s 变为有效字符串。

示例 4:

输入:s = "(((())(((())", locked = "111111010111"
输出:true
解释:locked 允许我们改变 s[6] 和 s[8]。
我们将 s[6] 和 s[8] 改为 ')' 使 s 变为有效字符串。

提示:

  • n == s.length == locked.length
  • 1 <= n <= 10^5
  • s[i] 要么是 '(' 要么是 ')'
  • locked[i] 要么是 '0' 要么是 '1'

Approach

  1. Check Length Parity: First, check if the length of the string is even. If it's odd, it's impossible to form valid parentheses, so return false immediately.
  2. Track Balance Range: Use two variables, min_balance and max_balance, to track the minimum and maximum possible balance at each step. The balance is calculated as the number of '(' minus the number of ')'.
  3. Update Balance: For each character in the string:
    • If the character is locked, update both min_balance and max_balance based on whether it's '(' or ')'.
    • If the character is unlocked, it can be either '(' or ')', so update max_balance as if it were '(' and min_balance as if it were ')'.
  4. Adjust Balance Constraints: After each update, if max_balance becomes negative, return false immediately as it's impossible to recover. Adjust min_balance to be non-negative since negative balance at any point is invalid.
  5. Final Check: After processing all characters, check if the final balance can be zero, i.e., min_balance ≤ 0 ≤ max_balance.
python
class Solution:
    def canBeValid(self, s: str, locked: str) -> bool:
        n = len(s)
        if n % 2 != 0:
            return False
        
        min_balance = 0
        max_balance = 0
        
        for i in range(n):
            char = s[i]
            lock = locked[i]
            
            if lock == '1':
                if char == '(':
                    min_balance += 1
                    max_balance += 1
                else:
                    min_balance -= 1
                    max_balance -= 1
            else:
                # Can choose '(' or ')'
                max_balance += 1
                min_balance -= 1
            
            # If max_balance is negative, it's impossible
            if max_balance < 0:
                return False
            
            # Ensure min_balance is at least 0
            min_balance = max(min_balance, 0)
        
        return min_balance <= 0 <= max_balance