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 dp[i] = (i \geq 2 ? dp[i - 2] : 0) + 2 dp[i]=(i≥2?dp[i−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 dp[i] = (i - dp[i - 1] \geq 2 ? dp[i - dp[i - 1] - 2] : 0) + dp[i - 1] + 2 dp[i]=(i−dp[i−1]≥2?dp[i−dp[i−1]−2]:0)+dp[i−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}}, dp[i]) maxLen=max(maxLen,dp[i])

遍历结束后,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;
    }
};
相关推荐
yuanbenshidiaos3 分钟前
c++---------数据类型
java·jvm·c++
十年一梦实验室32 分钟前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
AI莫大猫33 分钟前
(6)YOLOv4算法基本原理以及和YOLOv3 的差异
算法·yolo
taoyong00136 分钟前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我5842 分钟前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
Uu_05kkq1 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
fpcc1 小时前
跟我学c++中级篇——C++中的缓存利用
c++·缓存
呆萌很1 小时前
C++ 集合 list 使用
c++
诚丞成2 小时前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++
清梦20202 小时前
经典问题---跳跃游戏II(贪心算法)
算法·游戏·贪心算法