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:
'(' must have a corresponding right parenthesis ')'.')' must have a corresponding 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: "()" Output: True
Example 2:
Input: "(*)" Output: True
Example 3:
Input: "(*))" Output: True
Note:
Intuition and Algorithm
\nFor each asterisk, let\'s try both possibilities.
\n\nComplexity Analysis
\nTime Complexity: , where is the length of the string. For each asterisk we try 3 different values. Thus, we could be checking the validity of up to strings. Then, each check of validity is .
\nSpace Complexity: , the space used by our character array.
\nIntuition and Algorithm
\nLet dp[i][j] be true if and only if the interval s[i], s[i+1], ..., s[j] can be made valid.  Then dp[i][j] is true only if:
s[i] is \'*\', and the interval s[i+1], s[i+2], ..., s[j] can be made valid;
or, s[i] can be made to be \'(\', and there is some k in [i+1, j] such that s[k] can be made to be \')\', plus the two intervals cut by s[k] (s[i+1: k] and s[k+1: j+1]) can be made valid;
Complexity Analysis
\nTime Complexity: , where  is the length of the string.  There are  states corresponding to entries of dp, and we do an average of  work on each state.
Space Complexity:  , the space used to store intermediate results in dp.
Intuition
\nWhen checking whether the string is valid, we only cared about the "balance": the number of extra, open left brackets as we parsed through the string.  For example, when checking whether \'(()())\' is valid, we had a balance of 1, 2, 1, 2, 1, 0 as we parse through the string: \'(\' has 1 left bracket, \'((\' has 2, \'(()\' has 1, and so on.  This means that after parsing the first i symbols, (which may include asterisks,) we only need to keep track of what the balance could be.
For example, if we have string \'(***)\', then as we parse each symbol, the set of possible values for the balance is [1] for \'(\'; [0, 1, 2] for \'(*\'; [0, 1, 2, 3] for \'(**\'; [0, 1, 2, 3, 4] for \'(***\', and [0, 1, 2, 3] for \'(***)\'.
Furthermore, we can prove these states always form a contiguous interval.  Thus, we only need to know the left and right bounds of this interval.  That is, we would keep those intermediate states described above as [lo, hi] = [1, 1], [0, 2], [0, 3], [0, 4], [0, 3].
Algorithm
\nLet lo, hi respectively be the smallest and largest possible number of open left brackets after processing the current character in the string.
If we encounter a left bracket (c == \'(\'), then lo++, otherwise we could write a right bracket, so lo--.  If we encounter what can be a left bracket (c != \')\'), then hi++, otherwise we must write a right bracket, so hi--.  If hi < 0, then the current prefix can\'t be made valid no matter what our choices are.  Also, we can never have less than 0 open left brackets.  At the end, we should check that we can have exactly 0 open left brackets.
Complexity Analysis
\nTime Complexity: , where is the length of the string. We iterate through the string once.
\nSpace Complexity:  , the space used by our lo and hi pointers.  However, creating a new character array will take  space.
Analysis written by: @awice
\n