32. Longest Valid Parentheses

题目

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

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

Example 2:

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

题解

  • 题目的意思比较简单,给出一个只由左括号和右括号组成的字符串,求出有效的括号匹配最长长度

方法 1 - 利用stack

  • 利用数据结构stack完成,整个过程中stack的第一个元素为当前已遍历的不匹配括号串的最后一个')'的下标或者-1,其余在stack中存储的是字符'('的下标,参见阐述的步骤即可指定。使用stackFILO 的特性完成判断字符是否括号是否匹配以及计算有效匹配括号的长度
  • 步骤
    • 首先将-1推进stack
    • 遍历字符串,对于字符进行不同的处理
      • '(', 直接将其下标推入栈中-stack.push(i)
      • ')',首先弹出栈顶元素-stack.pop()。接下来的步骤需要划分两种情况进行:
      1. 如果当前栈中已经为空,即证明当前匹配的串已经无效,因为')'数目大于'('的数目,无法有效匹配括号,此时不做关于最长匹配的记录,只把当前下标推入栈中(当前')'的下标即为已遍历的不匹配括号串的最后一个')'的下标)
      2. 如果当前栈不为空,则证明目前匹配的串依旧有效,则更新一下最长匹配长度 - num = max(num, i - myStack.top())
  • 实现代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // stack
    class Solution {
    public:
    int longestValidParentheses(string s) {
    stack<int> myStack;
    myStack.push(-1);
    int num = 0;
    for(int i = 0; i < s.size(); ++i) {
    if(s[i] == '(')
    myStack.push(i);
    else {
    myStack.pop();
    if(myStack.empty())
    myStack.push(i);
    else {
    num = max(num, i - myStack.top());
    }
    }
    }
    return num;
    }
    };

方法 2 - 动态规划

  • 思路
    • 括号匹配的时候,遇到')'才可能成功匹配上。因此,使用一个数组num记录每个)最长有效匹配的长度。
    • 当前检索到')'有两种情况
      • 情况1: "...()..."
        • 这种至少匹配的长度是2,但是可能连着之前也是有可能满足的,例如"...()()..."这种情况,因此需要考虑连着已匹配的-(i >= 2 ? num[i-2] : 0)
        • 转移方程: num[i] = (i >= 2 ? num[i-2] : 0) + 2;
      • 情况2: "...))..."
        • 这种情况的匹配与前一个')'相关,如果前面是有效匹配的,则需要检查s[i-num[i-1]-1] == '('(条件:i >= num[i-1] + 1),即需要考虑"...((...))..."的情况。同时,还需要考虑前面是否可以与有效匹配的串连接起来,例如"...()((...))...",因此还需要考虑连着已匹配的-i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0
        • 转移方程:num[i] = num[i-1] + 2 + (i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0)
  • 实现代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // dp

    class Solution {
    public:
    int longestValidParentheses(string s) {
    if(!s.size()) return 0;
    int maxNum = 0;
    int num[s.size()] = {0};
    for(int i = 1; i < s.size(); ++i){
    if(s[i] == ')' && s[i-1] == '(') {
    // "...()..."
    num[i] = (i >= 2 ? num[i-2] : 0) + 2;
    }
    else if(s[i] == ')' && s[i-1] == ')' && i >= num[i-1] + 1 && s[i-num[i-1]-1] == '(') {
    // "...((...))..."
    num[i] = num[i-1] + 2 + (i >= num[i-1] + 2 ? num[i - num[i-1] - 2] : 0);

    }
    maxNum = max(maxNum, num[i]);
    }
    return maxNum;
    }
    };