Leetcode热题100-32 最长有效括号

Leetcode热题100-32 最长有效括号

1. 题目描述

32 最长有效括号

2. 解题思路

动态规划

定义状态:

  • dp[i] 表示以位置 i 结尾的最长有效括号子串的长度。

状态转移方程:

遍历字符串 s,当遇到 s[i] == ')' 时,存在以下两种情况:

  1. 情况 1:s[i - 1] == '('
    • 当前字符 ')' 与前一个字符 '(' 组成了一对匹配的括号。
    • 更新状态:
      d p i = ( i ≥ 2 ? d p i − 2 : 0 ) + 2 dpi = (i \geq 2 ? dpi - 2 : 0) + 2 dpi=(i≥2?dpi−2:0)+2
  2. 情况 2:s[i - 1] == ')'
    • 需要满足条件:i - dp[i - 1] > 0,即前面存在可以与当前 ')' 匹配的 '('
      d p i = ( i − d p i − 1 ≥ 2 ? d p i − d p \[ i − 1 − 2 ] : 0 ) + d p i − 1 + 2 dpi = (i - dpi - 1 \geq 2 ? dpi - dp\[i - 1 - 2] : 0) + dpi - 1 + 2 dpi=(i−dpi−1≥2?dpi−dp\[i−1−2]:0)+dpi−1+2
    • 其中:
      • dp[i - dp[i - 1] - 2] 表示与当前匹配的 '(' 前面的有效子串长度(若存在,否则为 0)。
      • dp[i - 1] 是前一个位置的最长有效子串长度。
      • s[i - dp[i - 1] - 1]s[i] 匹配(长度为 2)。

更新最大值:

在遍历过程中,更新最大长度:
maxLen = max ⁡ ( maxLen , d p i ) \text{{maxLen}} = \max(\text{{maxLen}}, dpi) maxLen=max(maxLen,dpi)

遍历结束后,maxLen 即为所求结果。

栈解法

初始化:

  • 使用一个栈 stk 存储索引。
  • -1 压入栈,表示最后一个未匹配的右括号的索引。

遍历字符串:

  • 遍历字符串中的每个字符:
    1. 如果当前字符为 '(',将其索引压入栈。
    2. 如果当前字符为 ')'
      • 弹出栈顶元素,表示尝试匹配最近的 '('
      • 如果栈为空,说明没有匹配的 '(',将当前索引压入栈。
      • 如果栈不为空,计算当前有效括号的长度,并更新最大长度 maxLen
        maxLen = max ⁡ ( maxLen , i − stack.top() ) \text{{maxLen}} = \max(\text{{maxLen}}, i - \text{{stack.top()}}) maxLen=max(maxLen,i−stack.top())

3. 代码实现

动态规划

cpp 复制代码
class Solution {
public:
    // 使用栈来解决问题
    int longestValidParentheses(string s) {
        int maxLen = 0;
        int n = s.size();
        vector<int> dp(n, 0);

        // 注意到子串是指字符串中连续的字符序列
        for (int i = 1; i < n; i++) {
            if (s[i] == ')') {
                // 直接匹配
                if (s[i - 1] == '(') {
                    dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
                }
                // s[i-1]=')'
                else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
                    // dp[i-dp[i-1]-2]表示与dp[i-1]相连的有效子字符串的长度
                    // dp[i]由三部分组成
                    // s[i-dp[i-1]-1]与s[i]匹配(长度为2)
                    // dp[i - 1]
                    // dp[i - dp[i - 1] - 2]或者为0
                    dp[i] = (i - dp[i - 1] >= 2 ? dp[i - dp[i - 1] - 2] : 0) +
                            dp[i - 1] + 2;
                }
            }
            maxLen = max(maxLen, dp[i]);
        }

        return maxLen;
    }
};

栈解法

cpp 复制代码
class Solution {
public:
    int longestValidParentheses(string s) {
        int res=0;
        stack<int> stk;
        stk.push(-1);
        for(int i=0;i<s.size();i++){
            if(s[i]=='('){
                stk.push(i);
            }else{
                stk.pop();
                if(stk.empty()){
                    stk.push(i);
                }else{
                    res=max(res,i-stk.top());
                }
            }
        }
        return res;
    }
};
相关推荐
WZF-Sang几秒前
TCP和UDP协议
linux·服务器·网络·c++·学习·tcp/ip·udp
Tim_109 分钟前
【C++】014、左值与右值的区别
开发语言·c++
想人陪的玫瑰11 分钟前
winform 能用 Native AOT 吗?——TDS 项目的实战尝试
c++·mfc
水龙吟啸12 分钟前
华为2026.6.24机考选择题+编程题【速刷敲黑板】
人工智能·深度学习·算法·机器学习·华为
Eloudy21 分钟前
全文 - Evolution Strategies as a Scalable Alternative to Reinforcement Learning
人工智能·算法
^yi36 分钟前
【C++】类和对象(全)
开发语言·c++
我不是懒洋洋40 分钟前
从零实现一个API网关:Kong的核心设计
c++
net3m3341 分钟前
可以加大adc滑动滤波的间隔时间,比如定时每20ms采集一次滤波输入,且用滑动窗口均值滤波
算法
2301_7779983444 分钟前
C++异常处理
c++
Dovis(誓平步青云)1 小时前
《C/C+++ Boost 轻量级搜索引擎实战:架构流程、技术栈与工程落地指南——HTML文件的清洗(上篇)》
开发语言·数据库·c++·搜索引擎·开源