算法题之最长有效括号的长度问题

算法题之最长有效括号的长度问题

问题描述

在这里插入图片描述

思路分析

在这里插入图片描述

代码实现
public int longestValidParentheses(String s) {
        if (s == null || s.length() <= 1) {
            return 0;
        }
        //定义一个栈
        Stack<Integer> stack = new Stack<>();
        int len = s.length();
        //定义一个maxLen
        int maxLen = 0;
        //先给栈空间压入一个初始值-1:由于一个有效括号为2个长度,保证判断括号的长度
        stack.push(-1);
        for (int i = 0; i < len; i++) {
            char val = s.charAt(i);
            //如果当前字符为'(':则直接将其进行压栈处理
            if (val == '(') {
                stack.push(i);
            }else {//如果添加的是')',则取出栈顶元素,判断当前栈是否为空,若为空,则直接将i进行入栈处理
                stack.pop();//出栈元素
                if (stack.empty()) {
                    stack.push(i);
                }else {
                    //maxLen为之前maxLen和i - stack.peek()的值的大小
                    maxLen = Math.max(maxLen,i - stack.peek());
                }
            }
        }
        return maxLen;
    }

在这里插入图片描述

代码实现
//动态规划进行求解
    public int longestValidParentheses(String s) {
        //如果s为null或者长度小等于1,则直接返回0
        if (s == null || s.length() <= 1) {
            return 0;
        }
        int len = s.length();
        char[] sArr = s.toCharArray();
        int[] dp = new int[len];//默认初始化为0
        //定义一个maxLength:存储最长有效括号的长度值
        int maxLength = 0;
        //遍历数组
        for (int i = 1; i < len; i++) {
            if (sArr[i] == ')') {//如果sArr[i]为')'
                if (sArr[i - 1] == '(') {//如果sArr[i - 1] == '('
                    if (i - 2 >= 0) {//判断sArr[i - 2]是否存在
                        dp[i] = dp[i - 2] + 2;
                    }else {
                        dp[i] = 2;
                    }
                }else {//如果sArr[i - 1] == ')'
                    if (i - dp[i - 1] - 1 >= 0) {//判断sArr[i - dp[i - 1] -1]是否存在,不存在,则说明不匹配,将dp[i] = 0(默认为0)
                        if (sArr[i - dp[i - 1] - 1] == '(') {
                            if (i - dp[i - 1] - 2 >= 0) {//判断sArr[i - dp[i - 1] -2]是否存在
                                dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2;
                            }else {
                                dp[i] = dp[i - 1] + 2;
                            }
                        }
                    }
                }
            }
            //如果sArr[i] = '(':则肯定无法构成有效括号,直接将dp[i] = 0(默认为0)

            //每一次计算完dp[i]的值,和maxLength进行比较,更新maxLength的值
            maxLength = Math.max(maxLength,dp[i]);
        }
        //for遍历结束,返回maxLength的值
        return maxLength;
    }

在这里插入图片描述

代码实现
//方法2:双指针完成.贪心算法实现
    //第一次遍历字符串:只考虑右括号比左括号少的情况
    //第二次遍历字符串:只考虑左括号比右括号少的情况
    //两种遍历结果的结合即完成了所有情况的遍历统计,以完成有效括号子串的最长长度的求解
    public int longestValidParentheses(String s) {
        //首先判断s字符串是否为null或者s的长度是否小于等于1:如果满足要求,则直接返回0
        if (s == null || s.length() <= 1) {
            return 0;
        }
        //定义两个指针left和right
        int left = 0;
        int right = 0;
        int maxLength = 0;//初始化最长有效括号子串长度为0
        //进行第一次遍历
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                left++;
            }else {//右括号
                right++;
            }
            if (left == right) {
                maxLength = Math.max(maxLength,2 * right);
            }else if (right > left) {
                left = right = 0;//剔除掉")(())"这种先右括号后左括号的情况:贪心地只考虑右括号比左括号少的情况
            }
        }
        //重置left和right指针的值
        left = right = 0;
        //进行第二次遍历(反向遍历)
        for (int i = s.length() - 1; i >=  0; i--) {
            if (s.charAt(i) == '(') {
                left++;
            }else {//右括号
                right++;
            }
            if (left == right) {
                maxLength = Math.max(maxLength,2 * left);
            }else if (left > right) {
                left = right = 0;//剔除掉"(())("这种先右后左情况:贪心地只考虑左括号比右括号少的情况
            }
         }

        //两次遍历:正序遍历和反序遍历结束以后
        return maxLength;
    }
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值