Valid Parenthesis String
MedPrompt
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: trueExample 2:
Input: s = "(*)"
Output: trueExample 3:
Input: s = "(*))"
Output: true
Constraints:
1 <= s.length <= 100s[i]is'(',')'or'*'.
Approaches
4 approaches with complexity analysis and trade-offs.
This approach explores every possible interpretation of the '' characters. For each '', we recursively try three possibilities: treating it as an opening parenthesis '(', a closing parenthesis ')', or an empty string. This exhaustive search checks if any combination results in a valid parenthesis string.
Algorithm
- Define a recursive function
check(s, index, openCount). indexis the current position in the string, andopenCountis the balance of open parentheses.- Base Case 1: If
openCountbecomes negative, it's an invalid state, returnfalse. - Base Case 2: If
indexreaches the end of the string, the string is valid if and only ifopenCountis 0. - Recursive Step:
- If
s[index]is'(', recurse withcheck(s, index + 1, openCount + 1). - If
s[index]is')', recurse withcheck(s, index + 1, openCount - 1). - If
s[index]is'*', explore all three possibilities by making three separate recursive calls:- Treat
*as'(':check(s, index + 1, openCount + 1). - Treat
*as')':check(s, index + 1, openCount - 1). - Treat
*as empty:check(s, index + 1, openCount).
- Treat
- Return
trueif any of the three branches for*returntrue.
- If
Walkthrough
We define a recursive function check(index, open_count) which determines if the substring starting from index is valid, given a current balance of open_count open parentheses.
- The base case for the recursion is when we reach the end of the string (
index == s.length()). The string is valid if and only if theopen_countis zero. - Another base case is if
open_countever becomes negative, which means we have an invalid sequence (e.g., a ')' without a preceding '('). In this case, we prune the search path by returningfalse. - In the recursive step, for the character at the current
index:- If it's '(', we increment
open_countand recurse on the next index. - If it's ')', we decrement
open_countand recurse. - If it's '*', we branch out and make three recursive calls: one for treating it as '(', one for ')', and one for an empty string. If any of these branches return
true, the string is valid.
- If it's '(', we increment
class Solution { public boolean checkValidString(String s) { return check(s, 0, 0); } private boolean check(String s, int index, int openCount) { if (openCount < 0) { return false; } if (index == s.length()) { return openCount == 0; } char c = s.charAt(index); if (c == '(') { return check(s, index + 1, openCount + 1); } else if (c == ')') { return check(s, index + 1, openCount - 1); } else { // c == '*' // Try all 3 possibilities for '*' return check(s, index + 1, openCount + 1) || // as '(' check(s, index + 1, openCount - 1) || // as ')' check(s, index + 1, openCount); // as empty } }}Complexity
Time
O(3^n), where n is the length of the string. In the worst case (a string of all '*'), we have 3 choices for each character, leading to an exponential number of paths.
Space
O(n), for the recursion stack depth, where n is the length of the string.
Trade-offs
Pros
Simple to understand and implement the core logic.
Correctly explores all possibilities.
Cons
Extremely inefficient due to its exponential time complexity.
Will result in a 'Time Limit Exceeded' error on most platforms for non-trivial inputs.
Solutions
Solution
class Solution {public boolean checkValidString(String s) { int x = 0; int n = s.length(); for (int i = 0; i < n; ++i) { if (s.charAt(i) != ')') { ++x; } else if (x > 0) { --x; } else { return false; } } x = 0; for (int i = n - 1; i >= 0; --i) { if (s.charAt(i) != '(') { ++x; } else if (x > 0) { --x; } else { return false; } } return true; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.