32-最长有效括号

题目

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = “(()”
输出:2
解释:最长有效括号子串是 “()”

示例 2:

输入:s = “)()())”
输出:4
解释:最长有效括号子串是 “()()”

示例 3:

输入:s = “”
输出:0

题解一 动态规划

class Solution {
    public int longestValidParentheses(String s) {
        if(s.length()==0){
            return 0;
        }
        int[] dp=new int[s.length()];
        int maxNum=0;//通过两两比较,得出dp数组中最大的数
        for(int i=1;i<dp.length;i++){//i=0的时候肯定是0!
            if(s.charAt(i)==')'){//(肯定为0,就不用算了
                if(s.charAt(i-1)=='('){
                    dp[i]=(i>1?dp[i-2]:0)+2;//若i=1,则直接0+2!***
                }else if((i-dp[i-1]-1)>=0&&s.charAt(i-dp[i-1]-1)=='('){//i是从0开始的,不能在索引里判断。而且这里的判断语句就有问题!i<=1了!应该把这个判断语句放到里面写!
                //i-dp[i-1]>0只是为了保证charAt存在!
                    dp[i]=dp[i-1]+((i-dp[i-1]-2)>=0?dp[i-dp[i-1]-2]:0)+2;
                }
            }
            maxNum=Math.max(dp[i],maxNum);
        }
        return maxNum;
    }
}

笔记:

  1. 动态规划题目分析的 4 个步骤:
    • 确定状态
      • 研究最优策略的最后一步
      • 化为子问题
    • 转移方程
      • 根据子问题定义得到
    • 初始条件和边界情况
    • 计算顺序
  2. 最优策略的最后一步:

i−dp[i−1]−1:i减掉中间匹配上的对数

考虑最后一个元素s[i]的情况:

  • s[i]=’(’:dp[i]=0

  • s[i]=’)’:

    • s[i-1]=’(’:dp[i]=dp[i-2]+2
    • 形如()((…)):dp[i]=dp[i-1]+dp[i-dp[i-1]-2]+2

    dp[i-1]:里层小括号的匹配数;dp[i-dp[i-1]-2]:

    因为有两个(的时候dp就置0了,所以需要加上两个dp的计数

  1. 注意!dp[i]的判断要在表达式内完成!并不是说>1之类的成立了就直接加2了,可能这一部分dp为0,但是还是要+2

题解二 栈

class Solution {
    public int longestValidParentheses(String s) {
        int ans=0;
        Deque<Integer> stack=new LinkedList<>();
        stack.push(-1);
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='('){
                stack.push(i);
            }else{
                stack.pop();
                if(stack.isEmpty()){
                    stack.push(i);
                }else{
                    ans=Math.max(i-stack.peek(),ans);
                }
            }
        }
        return ans;
    }
}

思路:

  1. 注意这个思路

  2. 保持栈底的元素为最后一个没有匹配上的右括号的下标。(为了保证如果第一个括号是左括号,栈底不是没有匹配上的右括号的下标,首先在栈底放入-1作为边界条件)将每个(的下标放入栈中,作为匹配,先弹出栈顶元素表示匹配了)。如果遇到),查看栈里有没有元素。如果栈为空,则将)的下标放入栈中,更新最后一个没有匹配上的右括号的下标。如果栈不为空,则将当前)的下标减去栈顶元素的下标,即是目前最长有效括号的长度。

  3. 注意栈的初始化方法!

    Deque stack = new LinkedList();

解法三 最大最小值 贪心法

class Solution {
    public int longestValidParentheses(String s) {
        int left=0;
        int right=0;
        int maxNum=0;
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='('){
                left+=1;
            }else{
                right+=1;
            }if(left==right){//以right为基准计算括号对的数量,maxNum记录的是全局最大的
                maxNum=Math.max(right*2,maxNum);
            }else if(right>left){
                left=0;
                right=0;
            }
        }
        left=0;
        right=0;
        for(int i=s.length()-1;i>=0;i--){
            if(s.charAt(i)=='('){
                left+=1;
            }else{
                right+=1;
            }if(left==right){//以left为基准计算括号对的数量,maxNum记录的是全局最大的
                maxNum=Math.max(left*2,maxNum);
            }else if(right<left){
                left=0;
                right=0;
            }
        }
        return maxNum;
    }
}

思路:

  1. 利用两个计数器left和right。首先从左到右遍历字符串,遇到(就left+1,)就right+1.当left和right 的值相等时,记录有效字符串的长度,并与最长的长度比较。若right>left时,则将left和right置0,重新计算。

    但是这样计算就没有考虑到left>right的情况,即(()这种。所以再从右向左重复差不多的操作,当left>right的时候,left和right都置0。当left=right时,更新有效字符串的长度。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codrab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值