LeetCode 32. 最长有效括号

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

的长度。

示例 1:

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

示例 2:

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

示例 3:

输入:s = ""
输出:0

提示:

  • 0 <= s.length <= 3 * 104
  • s[i] 为 '(' 或 ')'

解答:

可以通过使用栈和动态规划两种方法来解决。

方法一:使用栈

利用栈来解决括号匹配的问题,具体步骤如下:

  1. 使用栈保存括号索引

    • 遍历字符串,遇到 '(' 将其索引入栈。
    • 遇到 ')' 时,如果栈不空且栈顶为 '(',说明找到了一对有效括号,可以计算当前有效括号的长度并更新最大长度。
    • 如果栈顶为 ')' 或者栈为空,则将当前 ')' 的索引入栈,作为之后可能有效括号的起始点。
  2. 遍历完成后计算最长有效长度

    • 如果栈为空,说明整个字符串是有效的括号,长度为字符串长度。
    • 否则,栈中剩下的元素表示无法匹配的括号位置,通过这些位置计算最长有效括号的长度。
      #include <stack>
      #include <string>
      #include <algorithm>
      
      using namespace std;
      
      class Solution {
      public:
          int longestValidParentheses(string s) {
              int maxLen = 0;
              stack<int> stk;
              stk.push(-1); // 先放入一个哨兵,用于计算有效长度
              
              for (int i = 0; i < s.length(); ++i) {
                  if (s[i] == '(') {
                      stk.push(i);
                  } else { // s[i] == ')'
                      stk.pop();
                      if (stk.empty()) {
                          stk.push(i); // 更新新的哨兵
                      } else {
                          maxLen = max(maxLen, i - stk.top());
                      }
                  }
              }
              
              return maxLen;
          }
      };
      

      方法二:使用动态规划

      动态规划的思路是定义一个 dp 数组,其中 dp[i] 表示以 s[i] 结尾的最长有效括号子串的长度。具体步骤如下:

    • 初始化:将 dp 数组全部初始化为 0。

    • 状态转移

      • 如果 s[i] 为 '(',dp[i] 必然为 0,因为不可能以 '(' 结尾形成有效括号。
      • 如果 s[i] 为 ')',需要判断前一个字符 s[i-1]
        • 如果 s[i-1] 为 '(',则 dp[i] = dp[i-2] + 2,即前一个有效括号子串的长度加上当前括号对的长度。
        • 如果 s[i-1] 为 ')' 并且 i-dp[i-1]-1 >= 0s[i-dp[i-1]-1] == '(',则 dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2]
    • 计算最大长度:遍历 dp 数组找出最大值作为结果。

      class Solution {
      public:
          int longestValidParentheses(string s) {
              int maxLen = 0; // 初始化最大有效括号长度为0。
              int n = s.length(); // 获取输入字符串的长度。
              vector<int> dp(n, 0); // 创建一个长度为n的数组dp,用于存储以每个位置结尾的最长有效括号长度。
      
              for (int i = 1; i < n; ++i) { // 从第二个字符开始遍历输入字符串。
                  if (s[i] == ')') { // 如果当前字符是右括号:
                      if (s[i - 1] == '(') { // 如果前一个字符是左括号:
                          dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2; // 更新dp[i]为前一个位置的有效括号长度加2。
                      } else if (i - dp[i - 1] > 0 && s[i - dp[i - 1] - 1] == '(') {
                          // 如果前一个字符是右括号,并且前一个有效括号的起始位置在当前位置之前,并且前一个有效括号的前一个字符是左括号:
                          dp[i] = dp[i - 1] + (i - dp[i - 1] >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
                          // 更新dp[i]为前一个有效括号的长度加上前一个有效括号之前的有效括号长度(如果有的话)再加2。
                      }
                      maxLen = max(maxLen, dp[i]); // 更新最大有效括号长度。
                  }
              }
      
              return maxLen; // 返回最终的最大有效括号长度。
          }
      };
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值