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:
- 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.- An empty string is also valid.
Example 1:
Input: "()" Output: True
Example 2:
Input: "(*)" Output: True
Example 3:
Input: "(*))" Output: True
Note:
- The string size will be in the range [1, 100].
1.O(n) 空间。用两个Stack<Integer>分别记录left和star出现的下标。导致失败的情况是:1.出现right的时候,left和star合起来都不够用了。2.遍历完以后left和star配对消不掉:表现为,栈顶的star下标比栈顶的left下标小 就好像*( ,或者star先被用完了(用最后返回left.isEmpty()来表现)。
2.O(1)空间。用两个int most, least记录着现在还有多少个left可用,区别是most记录把星号当left用的情况,least记录把星号当right用的情况。导致失败的情况是:1.出现right的时候,most都到0了。 2.遍历完以后,least还>0,说明最后星号不够抵消。 更新情况是这样的:1.出现left,most, least都++。2.出现right,most--, least没到0的话-- 3.出现star,most++, least没到0的话--。(23里都对least很宽容的原因是,用most到0就失败的机制,已经避免了right出现太多的情况,那这个时候出现right时least已经到0只能是因为中间出现过star帮忙消了left造成的,这时候你就不用多减了,当之前的star是空气,现在的right实打实地替代了前面那个*即可)
实现1:
class Solution { public boolean checkValidString(String s) { Stack<Integer> left = new Stack<>(); Stack<Integer> star = new Stack<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') { left.push(i); } else if (c == '*') { star.push(i); } else { if (!left.isEmpty()) { left.pop(); } else if (!star.isEmpty()) { star.pop(); } else { return false; } } } while (!left.isEmpty() && !star.isEmpty()) { int leftI = left.pop(); int starI = star.pop(); if (starI < leftI) { return false; } } return left.isEmpty(); } }
实现2:
class Solution { public boolean checkValidString(String s) { // number of '(' when treating '*' as '(' int most = 0; // number of '(' when treating '*' as ')' int least = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(') { least++; most++; } else if (c == ')') { if (least > 0) { least--; } most--; } else { if (least > 0) { least--; } most++; } if (most < 0) { return false; } } return least == 0; } }