【線性 dp】A015_LC_最長有效括號(棧 + dp / 空間壓縮)

一、Problem

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

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

二、Solution

這題最樸素的做法是枚舉每一段子串,然後用棧檢查每一段子串是否合法,並記錄合法子串的長度,這種方法我試過,會超時…

方法一:棧 + dp

思路

如果當前字符 s[i] 爲右括號 ),我們很容易想到要找到一個最近的左括號 ( 與之匹配,找最近的左括號 ( 可以用變量記錄,但我們還要保存之前遇到的左括號 (,基於這一點我們要可用棧保存左括號的位置,最近的左括號就是棧頂元素

  • 定義狀態
    • f[i]f[i] 表示位置 ii 之前的最長有效括號長度
  • 思考初始化:
    • f[0:]=0f[0:] = 0
  • 思考狀態轉移方程
    • f[i]=f[j1]+(ij+1)j )f[i] = f[j-1] + (i-j+1)(j\ 是棧頂元素):表示如果 ii 位置是右括號 ((jj 位置是最接近它的左括號,那麼位置 ii 的長度就可以承接 j1j-1 之前的長度,
  • 思考輸出max(f[0:])max(f[0:])
class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.size(), ans = 0;
        stack<int> st;
        vector<int> f(n);

        for (int i = 0; i < n; i++) {
        	if (s[i] == '(') 
        		st.push(i);
        	else if (!st.empty()) {
        		int j = st.top(), len = i-j+1; st.pop();
        		if (j > 0) f[i] = f[j-1] + len;
        		else       f[i] = len;
        		if (f[i] > ans)
        			ans = f[i];
        	}
        }
        return ans;
    }
};

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)

最近我都在用 C++ 做,真的很方便丫丫,大愛 C++


方法二:空間壓縮

既然 dp 數組的值就是最長有效括號的長度,我們又知道有效括號的最小長度爲 2,所以我們可以用索引 ii 減去 dp 的值來判斷在 ii 位置前是否存在有效括號(i-dp[i-1] > 0 表示存在),這樣可以把棧空間省去…


複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章