力扣第32题 困难难度 最长有效括号,浪费两天没做出来!

博客作者分享了在解决LeetCode的32题——最长有效括号问题时,从暴力解法到动态规划思路的转变过程。作者最初尝试使用栈来解决,但在处理特殊情况上遇到困难,浪费了两天时间。后来通过分析答案,理解了动态规划的正确解法:通过维护一个动态规划数组,检查每对括号是否有效,并更新最长有效括号长度。博客详细解释了动态规划解决方案的逻辑,并给出了相应的代码实现。
摘要由CSDN通过智能技术生成

先看一眼题:
在这里插入图片描述
总觉得用暴力解法+debug一定能出答案,只差那么临门一脚,结果这一脚足足浪费了两天时间,应该做不出来就看答案的!
先总结一下我原来的思路吧:

//32.最长有效括号
//难点:()(()的结果是2,不是4 同时要满足(()的结果是2,而不是0
//难点:同时满足()(()的结果是2,()(())的结果是6,而不能是4
public class Solution32 {
    public static int longestValidParentheses(String s) {
        int sum = 0;
        int maxSum = 0;
        Stack stack = new Stack();
        char pre = '@';
        for (int i = 0; i < s.length();i++ ) {
            if (s.charAt(i) == '(') {
                stack.push('(');
            } else if (s.charAt(i) == ')') {
                try{
                    pre= (char) stack.pop();
                    sum+=2;
                    boolean boo=false;//boo用于判断当前位置之后是不是都只有左括号
                    int k;
                    for(k=i+1;k<s.length();k++){
                        if(s.charAt(k)!='(') break;
                    }
                    if(k==s.length()){
                        boo=true;
                    }
                    if((i+1==s.length()||boo)&&!stack.empty()){
                        //透支减二法,无法适用于特殊情况:从第一个右括号开始(该右括号前面必须有若干左括号),后面全部都是一个左括号一个右括号的情况
                        //()(()、()((())、()((()())
                        //(()()
                        sum-=2;
                        //判断是否为特殊情况
                        //首先找到第一个右括号
                        int j;
                        Stack specialStack = new Stack();
                        for(j = 0 ; j < s.length() && s.charAt(j)!=')' ; j++){
                            specialStack.push(s.charAt(j));
                        }
                        //判断这个右括号前面有没有左括号
                        if(specialStack.empty()){
                            //如果没有左括号,则找到第一个左括号
                            for(;j<s.length()&&s.charAt(j)!='(';j++){}
                            //然后找到第一个右括号
                            for(;j<s.length()&&s.charAt(j)!=')';j++){}
                        }
                        //判断是不是一个左一个右的循环
                        boolean yes = true;
                        j++;
                        while (j<s.length()){
                            if(!s.substring(j,j+2).equals("()")){
                                yes=false;
                                break;
                            }
                            j+=2;
                        }
                        if(yes)
                            sum+=2;
                    }
                }catch (Exception e){
                    //())的情况和()))的情况:当前子串sum应该=2
                    //)))的情况:当前子串sum应该=0
                    if(pre=='('){
                        sum=0;
                    }else if(pre=='@'){
                        sum=0;
                    }
                    pre='@';
                }
            }
            if (sum > maxSum)
                maxSum = sum;
        }
        return maxSum;
    }
}

看了答案,正确思路应该是动态规划。
根据动态规划思路写代码:

//动态规划法
    public static int longestValidParentheses_right1(String s){
        //两两检查,如果是()的形式,的dp[i]=dp[i-2]+2
        //        如果是()的形式,则寻找当前最长子串前面有没有可以匹配的左括号
        int[] dp = new int[s.length()];//初值都为0
        int max = 0;
        for(int i = 1 ; i < s.length() ; i++){
            if(s.charAt(i-1)=='('&&s.charAt(i)==')'){
                if(i==1)
                    dp[i]=2;
                else
                    dp[i]=dp[i-2]+2;
            }
            if(s.charAt(i-1)==')'&&s.charAt(i)==')'){
                //看看i-1为截止点的最长子串的前面一个位置是不是(,如果是的话,说明可以找到一个正确的(来匹配当前的)
                if(i-1-dp[i-1]<0){
                    //())的情况
                    dp[i]=0;
                }else if(s.charAt(i-1-dp[i-1])=='(')
                    //(  )  (  (  )  )
                    //0  2  0  0  2  6
                    dp[i]=dp[i-1]+dp[i-1-dp[i-1]-1 < 0 ? 0 : i-1-dp[i-1]-1]+2;
            }
            if(dp[i]>max)
                max=dp[i];
        }
        return max;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值