LeetCode 32. 最長有效括號
阿新 • • 發佈:2020-12-24
演算法1
兩遍線性掃描+貪心\(O(n)\)
線性掃描一遍字串,設定sum = 0
,假如是(
,就+1,假如是)
,就-1;計算完之後判斷一下當前的和,如果sum == 0
說明是有效字串,統計一下結果。如果是sum < 0
說明)
太多了,這種情況無論我們輸入什麼都沒法形成有效匹配,如果是sum > 0
,說明(
太多了,這種情況我們輸入)
,是可以生成有效匹配的。
但是隻是這樣的話,有一種情況會覆蓋不到,那就是掃描到最後,sum > 0
,但是字串裡確實有有效串。如...(((()((
,最中間的有效匹配會匹配不到。所以我們逆向思維,將整個過程反著來一遍就行了。
時間複雜度
\(O(n)\)
空間複雜度
\(O(1)\)
class Solution { public: int longestValidParentheses(string s) { if (s.empty()) return 0; int start = 0, sum = 0, res = 0; for (int i = 0; i < s.size(); i ++) { if (s[i] == '(') sum ++; else if (s[i] == ')') sum --; if (sum < 0) start = i + 1, sum = 0; else if (sum == 0) res = max(res, i - start + 1); } start = s.size()-1, sum = 0; for (int i = s.size()-1; i >= 0; i --) { if (s[i] == ')') sum ++; else if (s[i] == '(') sum --; if (sum < 0) start = i - 1, sum = 0; else if (sum == 0) res = max(res, start - i + 1); } return res; } };
演算法2
(動態規劃)\(O(n)\)
時間複雜度
\(O(n)\)
空間複雜度
\(O(n)\)
class Solution { public: int longestValidParentheses(string s) { int n = s.size(); if (!n) return 0; vector<int> f(n, 0); for (int i = 1; i < n; i ++) { if (s[i] == ')') { if (s[i-1] == '(') { if (i >= 2) f[i] = f[i-2] + 2; else f[i] = 2; } else { if (i-1-f[i-1] >= 0 && s[i-1-f[i-1]] == '(') if (i - f[i-1] - 2 >= 0) f[i] = f[i-1] + 2 + f[i - f[i-1] - 2]; else f[i] = f[i-1] + 2; } } } int res = 0; for (int i = 0; i < n; i ++) res = max(res, f[i]); return res; } };
Tip
寫動規一定要注意轉移方程、條件各個地方的下標!
演算法3
棧 \(O(n)\)
用棧來維護字串中待匹配的(
,用start
來記錄當前可能形成最長合法字串的起始位置。
- 噹噹前輸入的字串為
(
時,直接入棧 - 當輸入
)
,但是棧為空,說明不會再有輸入能合法化目前的字串,更新start = i + 1
。 - 當輸入
)
,但是棧不為空,棧頂元素出棧,若之後棧為空,說明找到了一個完全合法的子串,更新一下答案res=max(res, i - start + 1)
;若之後棧不為空,說明找到了一個部分合法的子串,更新一下答案為res = max(res, i - st.top())
。
時間複雜度
每個元素最多隻會入棧出棧一次,因此是\(O(n)\)
空間複雜度
\(O(n)\)
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
if (!n) return 0;
stack<int> st;
int start = 0, res = 0;
for (int i = 0; i < n; i ++)
{
if (s[i] == '(') st.push(i);
else
{
if (st.empty()) start = i + 1;
else
{
st.pop();
if (st.empty()) res = max(res, i - start + 1);
// 忘了
else res = max(res, i - st.top());
}
}
}
return res;
}
};
Tip
更進一步想,演算法1是不是演算法2更進一步思考的結果?演算法2中棧的元素,假如我們也按演算法1給它計算一下,是不是也是滿足相應的關係?