精选leetCode第32题最长有效括号(计数,递归)

大家好,我是魔笑,我们一起加油

题目:

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

示例1:

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

示例2:

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

示例3:

输入:s = "((()))()"

输出:8

解释:最长有效括号子串是 "((()))()"

题解:

1,当我们从左往右遍历时,我们计算左右括号的数量,当右括号( “)” )数大的时候,我们就将其舍弃,因为,之后无论是左括号还是右括号,都没法合成右效括号,我们就将左右括号清零。

 2,以上面的条件看,我们始终是以做括号( "(" )开始,那么只要左阔号和右括号相等,那么肯定是有效括号,当右括号大时,那么肯定有效括号中断,那么我们就将所有舍弃,再找最长的有效括号,如:

 3,还有一种情况,我们没法取得,就是,左括号一直大,所以我们得反方向再去找一遍,那么反向和正向互补,那么就能求得最终得有效括号,从左往右,不能相等,从右往左,两边括号数就能相等如图:

 

 

 

 代码1:

/**
 * leetcode第32题,最长有效括号
 */
public class Parentheses {
    //有效括号的数量
    private int max = 0;
    //左括号数
    private int right = 0;
    //右括号数
    private int left= 0;

    public int longestValidParentheses7(String s) {
        if (s.length() == 0) {
            return 0;
        }
        String[] split = s.split("()");
        int length = split.length;

        //先从左往右遍历
        for (int i = 0; i < length; i++) {
            calculate1(split, i, 0);
        }
        left = 0;
        right = 0;
        //再从右往左遍历
        for (int i = length - 1; i > 0; i--) {
            calculate1(split, i, 1);
        }
        return max;
    }
    public void calculate1(String[] split,  int i, int direction) {
        if (split[i].equals("(")) {
            left++;
        } else {
            right++;
        }
        //当左括号数和右括号数相等时(是有效括号),计算出有效的括号
        if (left == right) {
            max = max >= (left + right) ? max : (left + right);
        }
        //从左往右遍历是,当右括号数大时,舍弃,将状态重置。
        //从右往左遍历是,当左括号数大时,舍弃,将状态重置。
        switch (direction) {
            case 0:
                if (right > left) {right = 0;left = 0;}
                break;
            case 1:
                if (left > right) {right = 0;left = 0;}
                break;
            default:
                break;
        }
    }
    }

代码2:

public class Parentheses {
    //有效括号的数量
    private int max = 0;
    //左括号数
    private int right = 0;
    //右括号数
    private int left= 0;
 
public int longestValidParentheses(String s) {
        if (s.length() == 0) {
            return 0;
        }
        String[] split = s.split("()");
        int length = split.length;

        int right= 0;
        int left= 0;
        //先从左往右遍历
        calculate(split, 0,length, right, left, 0);
       //再从右往左遍历
        calculate(split, length-1,length, right, left, 1);
        return max;
    }
    public void calculate(String[] split, int i,int length, int right, int left, int direction) {
        if (split[i].equals("(")) {
            left++;
        } else {
            right++;
        }
        当左括号数和右括号数相等时(是有效括号),计算出有效的括号
        if (left == right) {
            max = max >= (left + right) ? max : (left + right);
        }
         //从左往右遍历是,当右括号数大时,舍弃,将状态重置。
        //从右往左遍历是,当左括号数大时,舍弃,将状态重置。
        switch (direction) {
            //从左往右遍历
            case 0:
                if (right > left) {right = 0;left = 0;}
                break;
            //从右往左遍历
            case 1:
                if (left > right) {right = 0;left = 0;}
                break;
            default:
                break;
        }
        //从左往右遍历
        if(direction==0&&i+1<length){
            calculate(split, ++i,length, right, left, 0);

        }
        //从右往往遍历
        if(direction==1&&i-1>=0){
            calculate(split, --i,length, right, left, 1);
        }
        return;
    }
}

如果对你有帮助,请给一个素质三连,谢谢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值