Problem
A parentheses string is a non-empty string consisting only of '(' and ')'. It is valid if any of the following conditions is true:
- It is
(). - It can be written as
AB(Aconcatenated withB), whereAandBare valid parentheses strings. - It can be written as
(A), whereAis a valid parentheses string.
You are given a parentheses string s and a string locked, both of length n. locked is a binary string consisting only of '0's and '1's. For each index i of locked,
- If
locked[i]is'1', you cannot changes[i]. - But if
locked[i]is'0', you can changes[i]to either'('or')'.
Return true if you can make s a valid parentheses string. Otherwise, return false.
Examples
Example 1:
$$ \begin{array}{|c|c|c|c|c|c|} \hline \text{Index} & 0 & 1 & 2 & 3 & 4 & 5 \\ \hline s & ) & ) & ( & ) & ) & ) \\ \hline \text{locked} & 0 & \colorbox{red} 1 & 0 & \colorbox{red} 1 & 0 & 1 \\ \hline \text{Changed} & \colorbox{RoyalBlue} ( & ) & ( & ) & \colorbox{RoyalBlue} ( & ) \\ \hline \end{array} $$
| |
Example 2:
| |
Example 3:
| |
Constraints:
n == s.length == locked.length1 <= n <= 105s[i]is either'('or')'.locked[i]is either'0'or'1'.
Solution
Method 1 - Using Stack
Here is the approach:
- Two Stacks:
- One stack to keep track of open parentheses.
- Another stack to keep track of flexible positions where characters can be changed.
- Pass through the String: Traverse the string:
- Push the index of
'('characters onto the open stack if it is locked (locked[i] == '1'), or onto the flexible stack if it is unlocked (locked[i] == '0'). - Push the index of
')'characters directly onto another stack if it is locked.
- Push the index of
- Balancing using Stacks:
- Try to balance each ‘)’ with the corresponding ‘(’ from the open stack first.
- If ‘(’ is unavailable (i.e., the stack is empty), try to use a flexible position from the flexible stack.
- Ensure that flexible positions can be used appropriately to convert to ‘(’ or ‘)’ to balance the string.
- Final Check:
- Ensure all open parentheses can be balanced by available flexible positions.
Code
| |
| |
Complexity
- ⏰ Time complexity:
O(n), wherenis the length of the string because each character is processed once. - 🧺 Space complexity:
O(n), due to the use of stacks to hold the indices.
Method 2 - Two Pass
To determine if a string of parentheses can be transformed into a valid parentheses string given the constraints, we need to ensure that:
- We have an equal number of
'('and')'; - At any point in parsing the string, the number of closing parentheses should not exceed the number of opening parentheses;
- Respect the constraints provided by the
lockedstring.
To determine if a string of parentheses can be transformed into a valid parentheses string given the constraints, we need to ensure that:
- Even Length:
- The string length must be even. If
s.length()is odd, returnfalse.
- The string length must be even. If
- Balanced Parentheses:
- We have an equal number of
'('and')'.
- We have an equal number of
- No Premature Closing Parentheses:
- At any point in parsing the string, the number of closing parentheses
')'should not exceed the number of opening parentheses'('.
- At any point in parsing the string, the number of closing parentheses
- Respect Locked Constraints:
- The
lockedstring provides constraints on which parentheses can be altered. Any position wherelocked[i] == '1'is immutable.
- The
Approach
- Forward Pass (Left to Right):
- Track the balance of opening and closing parentheses.
- Use two counters:
openfor fixed opening parentheses andflexiblefor flexible positions. - Traverse the string from left to right:
- Increment
flexiblefor positions that can be changed (locked[i] == '0'). - Increment
openfor fixed opening parentheses'('. - For a closing parenthesis
')', decrementopenif available; otherwise, useflexible. If neither is available, returnfalse.
- Increment
- Ensure that at any point, the number of closing parentheses does not exceed the number of opening parentheses when considering the flexible positions.
- Backward Pass (Right to Left):
- This helps balance any excess opening parentheses by utilizing available changes from the other direction.
- Use two counters:
closefor fixed closing parentheses andflexiblefor flexible positions. - Traverse the string from right to left:
- Increment
flexiblefor positions that can be changed (locked[i] == '0'). - Increment
closefor fixed closing parentheses')'. - For an opening parenthesis
'(', decrementcloseif available; otherwise, useflexible. If neither is available, returnfalse.
- Increment
- Ensure that at any point, the number of opening parentheses does not exceed the number of closing parentheses when considering the flexible positions.
Code
| |
| |
Complexity
- ⏰ Time complexity:
O(n), wherenis the length of the string since we are scanning the string twice. - 🧺 Space complexity:
O(1), as we are using a constant amount of extra space.