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 '*'.题目大意:
求给定字符串带星号是否合法括号配对。
Stack算法思路(推荐):
括号题优先考虑用Stack。如果不带星号,回忆合法括号题,有三种不合法情况,此题只需考虑两种,不需考虑多种括号类型
三种不合法情况: ‘[‘ (stack有余), ‘]’ (要匹配的时候stack为空)
难点: 
- 在于要去想多一个栈来存星号,因为星号可以作为左括号备选去match右括号。右括号在两个栈中优先配对左括号,星号可以为空。如果两个栈均为空,处理了第一种不合法情况
 - 循环后,如果两栈有余,分4中情况讨论:
1) 左括号栈有余星号栈空,正是第二种不合法情况
2) 左括号栈空星号栈空,合法
3) 左括号栈空星号栈有余,合法,星号可为空
4) 都有余,这是难点二。星号可以作为右括号去配对左括号,前提条件是星号在左括号之后,考虑*(,这是不合法 
注意事项:
- 如果for循环出来后,两栈不为空,要比较先后顺序
 - for loop后,L18 - Line 19记得pop,否则死循环
 
Python代码:
1  | def checkValidString(self, s: str) -> bool:  | 
算法分析:
时间复杂度为O(n),空间复杂度O(n)  
统计算法II解题思路:
括号题另一个常用思路是用统计左右括号数。此题较难想到是用一个左括号数量范围去验证。
lo为左括号的最少合法个数,hi为左括号的最大合法个数,有范围是因为星号可以变成左右括号或空。
遇到左括号,都加1,遇到右括号,都减1,遇到星号,假设星号为右括号,所以lo减1,hi加1.
如果hi小于0,表示最大左括号数小于右括号数,不满足此法的规则一,不合法  
难点在于lo设为非负。因为lo是最少且合法,合法意思是lo不是单纯地将所有星号变成右括号,而是当左括号不足时,用提高下限,将星号变成空,体现在令lo为非负。
for循环后,lo必须为0,运用了法则二,左右括号相等。  
Python代码:
1  | def checkValidString(self, s: str) -> bool:  | 
算法分析:
时间复杂度为O(n),空间复杂度O(n)  
DP算法III解题思路:
基本情况为s[i], s[j] 分别在(*, )* 就合法
如果用单边DP,并不能确定区间内那些合法,所以只能用区间型DP
dp[i][j] = s[i-1] == ‘*‘ and dp[i+1][j] 星号不匹配
         = s[i-1] in ‘(*‘ and dp[i+1][k-1] and s[k-1] in (‘)*‘) and dp[k+1][j] 星号匹配  
具体参考leetcode答案
DP基本情况比较难想出来且递归是复杂,实现易错,不推荐。不过可以多了解区间型DP的模式  
算法分析:
时间复杂度为O(n^3),空间复杂度O(n^2)  


