678. Valid Parenthesis String
Difficulty: Medium
Topics: String
, Dynamic Programming
, Stack
, Greedy
Given a string s
containing only three types of characters: '('
, ')'
and '*'
, return true
if s
is valid.
The following rules define a valid string:
- 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""
.
Example 1:
Input: s = "()"
Output: true
Example 2:
Input: s = "(*)"
Output: true
Example 3:
Input: s = "(*))"
Output: true
Constraints:
1 <= s.length <= 100
-
s[i]
is'(', ')'
or'*'
.
Hint:
- Use backtracking to explore all possible combinations of treating '*' as either '(', ')', or an empty string. If any combination leads to a valid string, return true.
- DP[i][j] represents whether the substring s[i:j] is valid.
- Keep track of the count of open parentheses encountered so far. If you encounter a close parenthesis, it should balance with an open parenthesis. Utilize a stack to handle this effectively.
- How about using 2 stacks instead of 1? Think about it.
Solution:
We can use a greedy approach with two counters to track the possible minimum and maximum number of open parentheses (
that could be valid at any point in the string.
Key Idea:
-
We maintain two counters:
minOpen
andmaxOpen
.-
minOpen
: Tracks the minimum number of open parentheses that could still be valid. -
maxOpen
: Tracks the maximum number of open parentheses that could still be valid.
-
-
As we iterate through the string:
- If the current character is
'('
, we increment bothminOpen
andmaxOpen
since we have one more possible open parenthesis. - If the current character is
')'
, we decrement bothminOpen
andmaxOpen
since we close one open parenthesis. - If the current character is
'*'
, we incrementmaxOpen
(treat*
as'('
), and we decrementminOpen
(treat*
as')'
or an empty string).
- If the current character is
If at any point
maxOpen
becomes negative, we know it's impossible to balance the parentheses, so the string is invalid.At the end,
minOpen
must be zero for the string to be valid. This ensures that all open parentheses have been closed.
Let's implement this solution in PHP: 678. Valid Parenthesis String
<?php
function checkValidString($s) {
...
...
...
/**
* go to ./solution.php
*/
}
// Test cases
echo checkValidString("()") ? "true" : "false"; // Output: true
echo "\n";
echo checkValidString("(*)") ? "true" : "false"; // Output: true
echo "\n";
echo checkValidString("(*))") ? "true" : "false"; // Output: true
?>
Explanation:
- We initialize two counters,
minOpen
andmaxOpen
. - As we traverse the string:
- For
'('
, both counters are incremented. - For
')'
, both counters are decremented (withminOpen
clamped to 0 to avoid negative values). - For
'*'
, we adjustminOpen
andmaxOpen
based on its flexibility (it can act as(
,)
, or""
).
- For
- If
maxOpen
becomes negative at any point, we returnfalse
because it's impossible to balance. - Finally, we return
true
only ifminOpen
is 0, meaning all open parentheses are properly closed.
Time Complexity:
- The time complexity is (O(n)), where (n) is the length of the string
s
, because we only traverse the string once.
Space Complexity:
- The space complexity is (O(1)) because we use only two integer variables (
minOpen
andmaxOpen
), regardless of the size of the input.
Output:
- For
s = "()"
, the output istrue
. - For
s = "(*)"
, the output istrue
. - For
s = "(*))"
, the output istrue
.
Contact Links
If you found this series helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!
If you want more helpful content like this, feel free to follow me:
Top comments (0)