[LeetCode] 32. Longest Valid Parentheses

題目鏈接: 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;
    }
};
發佈了60 篇原創文章 · 獲贊 18 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章