有效的括号字符串
问题描述
给定一个只包含三种字符的字符串:(、) 和 *,写一个函数来检验这个字符串是否为有效的。
有效字符串需满足以下条件:
- 任何左括号
(必须有相应的右括号) - 任何右括号
)必须有相应的左括号( - 左括号必须在对应的右括号之前
*可以被视为单个右括号),或单个左括号(,或一个空字符串- 空字符串也被视为有效字符串
示例:
输入: "()"
输出: True
输入: "(*)"
输出: True
输入: "(*))"
输出: True
算法思路
关键在于处理通配符 *,它有三种可能的用途。可以使用贪心算法或双栈方法来解决。
贪心算法思路:
- 维护两个变量:
minOpen(最少可能的未匹配左括号数)和maxOpen(最多可能的未匹配左括号数) - 遍历字符串:
- 遇到
(:minOpen++,maxOpen++ - 遇到
):minOpen--,maxOpen-- - 遇到
*:minOpen--(当作)),maxOpen++(当作()
- 遇到
- 约束条件:
minOpen不能小于0(因为不能有负的未匹配左括号)maxOpen不能小于0(如果小于0说明右括号太多,无法匹配)
- 最终
minOpen必须为0(所有左括号都被匹配)
双栈方法思路:
- 使用两个栈分别存储左括号和星号的索引
- 遍历字符串:
- 遇到
(:压入左括号栈 - 遇到
*:压入星号栈 - 遇到
):优先用左括号匹配,没有左括号就用星号匹配
- 遇到
- 处理剩余的左括号:用后面的星号来匹配前面的左括号
代码实现
方法一:贪心算法
class Solution {
/**
* 使用贪心算法验证括号字符串的有效性
* 维护最少和最多可能的未匹配左括号数量
*
* @param s 输入字符串,包含 '(', ')', '*'
* @return 字符串是否有效
*/
public boolean checkValidString(String s) {
int minOpen = 0; // 最少可能的未匹配左括号数(*当作)时)
int maxOpen = 0; // 最多可能的未匹配左括号数(*当作(时)
for (char c : s.toCharArray()) {
if (c == '(') {
// 遇到左括号,未匹配数量必然增加
minOpen++;
maxOpen++;
} else if (c == ')') {
// 遇到右括号,未匹配数量必然减少
minOpen--;
maxOpen--;
} else {
// c == '*'
// 星号可以当作右括号(减少未匹配数)或左括号(增加未匹配数)
minOpen--; // 当作右括号
maxOpen++; // 当作左括号
}
// minOpen不能小于0,因为不能有负的未匹配左括号
// 实际上,minOpen表示在最优情况下(尽可能多用*当作右括号)的未匹配数
if (minOpen < 0) {
minOpen = 0;
}
// 如果maxOpen小于0,说明即使把所有*都当作左括号也不够匹配右括号
if (maxOpen < 0) {
return

最低0.47元/天 解锁文章
642

被折叠的 条评论
为什么被折叠?



