32. Longest Valid Parentheses (H)

本文探讨了寻找字符串中连续匹配括号对的最长长度问题,介绍了三种解决方案:压栈法、左右扫描法和动态规划法,并提供了详细的代码实现。

Longest Valid Parentheses (H)

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

题意

给定一个只包含左右括号的字符串,输出连续匹配括号对的最长长度。

思路

个人想到的方法是压栈法:建两个栈,一个par存括号字符,另一个index存括号字符对应的下标。用i遍历字符串,如果为’(’,则同时压入两个栈;若为’)’,此时如果par为空,则压入par和index,如果par非空且栈顶元素为’(’,说明配对成功,同时出栈par和index,而此时index的栈顶元素(非空时)代表的是当前最右边无法匹配的括号的下标,那么 i - index.peek() (index非空)/ i + 1 (index为空) 就代表了新增一对匹配括号对后更新的连续匹配长度,将之与max比较并更新max。
官方的压栈法解答只使用了一个栈,但整体思路是一样的。

左右扫描法:设两个计数器left和right,先从左向右扫描字符串,’(‘则left+1,’)'则right+1,每扫描一个字符串,比较left和right,如果left < right,则将left和right重置,如果left == right,则更新max;同理再从右向左扫描,如果left > right,则将left和right重置,如果left == right,则更新max。
这是因为左右扫描,不能正确处理"( ) ( ( ( ) )“这种情况,而右左扫描可以;右左扫描不能正确处理”( ( ) ) ) ( )"这种情况,但左右扫描可以。

动态规划:dp数组记录以当前括号字符为结尾的最大有效长度,显而易见只有以’)‘为结尾才可能形成有效字符串,因此只有在当前字符为’)'时才进行处理,共可能会有以下两种情况:

  1. s[i] == ‘)’ && s[i - 1] == ‘(’,这时很容易得到 dp[i]=dp[i−2]+2dp[i] = dp[i - 2] + 2dp[i]=dp[i2]+2
  2. s[i] == ‘)’ && s[i - 1] == ‘)’,这种情况下,先找到以s[i - 1]为结尾的有效字符串开头的前一个字符c (当然如果dp[i - 1] == 0,就不需要找这个c了),如果c为’(’,则与s[i]构成匹配括号对,同时还要考虑以c前一个字符c’为结尾的有效字符串的长度 (举个例子,"( ) ( ( ) )",最后一个’)'为s[i]),最终得到 dp[i]=dp[i−1]+2+dp[i−dp[i−1]−2]dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]dp[i]=dp[i1]+2+dp[idp[i1]2]

代码实现 - 压栈法

class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;

        Deque<Character> par = new ArrayDeque<>();
        Deque<Integer> index = new ArrayDeque<>();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                par.push(c);
                index.push(i);
            } else {
                if (par.isEmpty() || par.peek() != '(') {
                    par.push(c);
                    index.push(i);
                } else {
                    par.pop();
                    index.pop();
                    max = Math.max(max, index.isEmpty() ? i + 1 : i - index.peek());
                }
            }
        }

        return max;
    }
}
class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;

        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(-1);

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                stack.push(i);
            } else {
                stack.pop();
                // 出栈后若栈空,说明出栈的是不匹配的')',将当前')'压入栈
                // 若栈非空,说明出栈的是匹配的'(',更新max
                if (stack.isEmpty()) {
                    stack.push(i);
                } else {
                    max = Math.max(max, i - stack.peek());
                }
            }
        }
        
        return max;
    }
}

代码实现 - 左右扫描法

class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;
        int left = 0, right = 0;

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                max = Math.max(max, left + right);
            } else if (left < right) {
                left = right = 0;
            }
        }

        left = right = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            char c = s.charAt(i);
            if (c == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                max = Math.max(max, left + right);
            } else if (left > right) {
                left = right = 0;
            }
        }
        
        return max;
    }
}

动态规划

class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;

        int[] dp = new int[s.length()];
        for (int i = 1; i < s.length(); i++) {
            if (s.charAt(i) == ')') {
                if (s.charAt(i - 1) == '(') {
                    dp[i] = i - 2 >= 0 ? dp[i - 2] + 2 : 2;
                } else {
                    if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
                        dp[i] = dp[i - 1] + 2 + (i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0);
                    }
                }
            }
        }
        
        for (int i = 0; i < s.length(); i++) {
            max = Math.max(max, dp[i]);
        }

        return max;
    }
}
【多变量输入超前多步预测】基于CNN-BiLSTM的光伏功率预测研究(Matlab代码实现)内容概要:本文介绍了基于CNN-BiLSTM模型的多变量输入超前多步光伏功率预测方法,并提供了Matlab代码实现。该研究结合卷积神经网络(CNN)强大的特征提取能力与双向长短期记忆网络(BiLSTM)对时间序列前后依赖关系的捕捉能力,构建了一个高效的深度学习预测模型。模型输入包含多个影响光伏发电的气象与环境变量,能够实现对未来多个时间步长的光伏功率进行精确预测,适用于复杂多变的实际应用场景。文中详细阐述了数据预处理、模型结构设计、训练流程及实验验证过程,展示了该方法相较于传统模型在预测精度和稳定性方面的优势。; 适合人群:具备一定机器学习和深度学习基础,熟悉Matlab编程,从事新能源预测、电力系统分析或相关领域研究的研发人员与高校研究生。; 使用场景及目标:①应用于光伏电站功率预测系统,提升电网调度的准确性与稳定性;②为可再生能源并网管理、能量存储规划及电力市场交易提供可靠的数据支持;③作为深度学习在时间序列多步预测中的典型案例,用于科研复现与教学参考。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注数据归一化、CNN特征提取层设计、BiLSTM时序建模及多步预测策略的实现细节,同时可尝试引入更多外部变量或优化网络结构以进一步提升预测性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值