[LeetCode] 32. Longest Valid Parentheses

来源:互联网 发布:吴彦祖 知乎 编辑:程序博客网 时间:2024/06/14 21:52

题目链接: https://leetcode.com/problems/longest-valid-parentheses/description/

Description

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

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

解题思路

整体思路为动态规划,用数组 dp[i] 记录以 s[i] 为最后一个字符的最长合法括号长度。

首先可以想到,合法的括号要包括 (),因此遍历字符串时,若遇到 ( 时可以暂时不管,仅当遇到 ) 时再来处理。另外,合法的括号主要有两种形式:

  • ()() => s[i] == ')' and s[i - 1] == '('
  • (()) => s[i] == ')' and s[i - 1] == ')'

先考虑第一种形式,容易想到只需要将 s[i - 2] 为最后一个字符的最长合法括号长度加 2 即可,即 dp[i] = dp[i - 2] + 2

第二种形式稍微复杂一点点,需要定位 s[i] 对应的另一个左括号 ( 的位置。因为 dp[i - 1] 记录了以 s[i - 1] 为结尾的最长合法括号长度,那么显然 i - dp[i - 1] - 1 就应该是 s[i] 对应的另一个左括号应该在的位置,dp[i - 1] 就是夹在这对外括号中间的最长合法括号长度。要计算 dp[i] 的话,还要考虑紧挨着这对外括号左侧的最长合法括号长度,因为子串可能为 "()(())",因此这种情况 dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]

对于为什么 i - dp[i - 1] - 1s[i] 对应的另一个左括号的位置,举个简单的例子看下。s = "(())",当遍历完前三个字符后 dp[] = {0, 0, 2, x}x 表示未知。此时来计算最后一个字符 s[3] 对应的 dp[3] 的值,可以看到 s[3] 对应的左括号应该就是下标为 i - dp[i - 1] - 1 = 3 - dp[2] - 1 = 0 的字符 s[0]

时间复杂度 O(n),空间复杂度 O(n)n 为字符串 s 的长度。

Code

class Solution {public:    int longestValidParentheses(string s) {        int maxLen = 0;        vector<int> dp(s.size());        for (int i = 1; i < s.size(); ++i) {            if (s[i] == ')' && s[i - 1] == '(') {                dp[i] = i > 1 ? dp[i - 2] + 2 : 2;            } else if (s[i] == ')' && s[i - 1] == ')' && s[i - dp[i - 1] - 1] == '(') {                if (i - dp[i - 1] - 2 >= 0)                    dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2];                else                    dp[i] = dp[i - 1] + 2;            }            maxLen = max(dp[i], maxLen);        }        return maxLen;    }};
原创粉丝点击