有效的括号字符串(力扣)动态规划、贪心 JAVA

给你一个只包含三种字符的字符串,支持的字符类型分别是 ‘(’、‘)’ 和 ‘*’。请你检验这个字符串是否为有效字符串,如果是有效字符串返回true 。

有效字符串符合如下规则:

任何左括号 ‘(’ 必须有相应的右括号 ‘)’。 任何右括号 ‘)’ 必须有相应的左括号 ‘(’ 。 左括号 ‘(’ 必须在对应的右括号之前 ‘)’。 ‘*’ 可以被视为单个右括号 ‘)’ ,或单个左括号 ‘(’ ,或一个空字符串。 一个空字符串也被视为有效字符串。

示例 1:

输入:s = “()”
输出:true

示例 2:

输入:s = “(*)”
输出:true

示例 3:

输入:s = “(*))”
输出:true

提示:

1 <= s.length <= 100
s[i] 为 ‘(’、‘)’ 或 ‘*’

解题思路:

1、最开始我的想法是利用单括号思维解决本题‘(’无非多了一个‘*’,谁缺给谁补,事实证明我的想法还是很有漏洞

错误代码:

class Solution {
	public int balance = 0, middle = 0;
    public boolean checkValidString(String s) {
         
        for(char a : s.toCharArray()) {
           if(a == '(') {
        	   if(check()) return false;
			       balance ++;
           }
           else if(a == ')') {
        	   balance --;
        	   if(check()) return false;
           }
           else if(a == '*') middle ++;
        }
				
        return balance == 0;
    }
  
    public boolean check() {
    	while(balance < 0 && middle > 0) {
    		balance ++;
    		middle --;
    	}
    	return balance < 0;
    }
}

在这里插入图片描述

上述代码有巨大漏洞即无法判别**((**))的对错,也就是说我没有考虑到*符号的位置的重要性

解决策略:记录下标和栈的引入

2、动态规划去一步一步分析,是可行的,因为其考虑到了‘*’在不同情况产生的不同结果

在这里插入图片描述

代码:

class Solution {
    public boolean checkValidString(String s) {
        int n = s.length();
        boolean[][] f = new boolean[n + 1][n + 1];
        f[0][0] = true;
        for (int i = 1; i <= n; i++) {
            char c = s.charAt(i - 1);
            for (int j = 0; j <= i; j++) {
                if (c == '(') {
                    if (j - 1 >= 0) f[i][j] = f[i - 1][j - 1];
                } else if (c == ')') {
                    if (j + 1 <= i) f[i][j] = f[i - 1][j + 1];
                } else {
                    f[i][j] = f[i - 1][j];
                    if (j - 1 >= 0) f[i][j] |= f[i - 1][j - 1];
                    if (j + 1 <= i) f[i][j] |= f[i - 1][j + 1];
                }
            }
        }
        return f[n][0];
    }
}

3、下述模拟也可以避免符号位置考虑不到的错误

在这里插入图片描述

代码:

class Solution {
    public boolean checkValidString(String s) {
        // l: 左括号最少可能有多少个
        // r: 左括号最多可能有多少个
        int l = 0, r = 0;
        for (char c : s.toCharArray()) {
            // 遇到'('所有可能性加一
            // 遇到')'所有可能性减一
            // 遇到'*',最少的可能性可以变少,最多的可能性也同样可以变多,这取决于这个星号最终我们看成什么,但是可能性都在
            if (c == '(') {
                l++; r++;
            } else if (c == ')') {
                l--; r--;
            } else {
                l--; r++;
            }
            // 当前左括号最少个数不能为负
            l = Math.max(l, 0);
            // 这种情况其实发生在r本身是负数的时候,也就是我们常见的右括号太多了
            if (l > r) return false;
        }
        // 能取到0个左括号才是满足平衡的
        return l == 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值