算法题 有效的括号字符串

有效的括号字符串

问题描述

给定一个只包含三种字符的字符串:()*,写一个函数来检验这个字符串是否为有效的。

有效字符串需满足以下条件:

  1. 任何左括号 ( 必须有相应的右括号 )
  2. 任何右括号 ) 必须有相应的左括号 (
  3. 左括号必须在对应的右括号之前
  4. * 可以被视为单个右括号 ),或单个左括号 (,或一个空字符串
  5. 空字符串也被视为有效字符串

示例

输入: "()"
输出: True

输入: "(*)"
输出: True

输入: "(*))"
输出: True

算法思路

关键在于处理通配符 *,它有三种可能的用途。可以使用贪心算法双栈方法来解决。

贪心算法思路

  1. 维护两个变量:minOpen(最少可能的未匹配左括号数)和 maxOpen(最多可能的未匹配左括号数)
  2. 遍历字符串:
    • 遇到 (minOpen++, maxOpen++
    • 遇到 )minOpen--, maxOpen--
    • 遇到 *minOpen--(当作)), maxOpen++(当作(
  3. 约束条件:
    • minOpen 不能小于0(因为不能有负的未匹配左括号)
    • maxOpen 不能小于0(如果小于0说明右括号太多,无法匹配)
  4. 最终 minOpen 必须为0(所有左括号都被匹配)

双栈方法思路

  1. 使用两个栈分别存储左括号和星号的索引
  2. 遍历字符串:
    • 遇到 (:压入左括号栈
    • 遇到 *:压入星号栈
    • 遇到 ):优先用左括号匹配,没有左括号就用星号匹配
  3. 处理剩余的左括号:用后面的星号来匹配前面的左括号

代码实现

方法一:贪心算法

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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值