最長有效括號
題目描述
給定一個只包含 '('
和 ')'
的字符串,找出最長的包含有效括號的子串的長度。
示例 1:
輸入: "(()"
輸出: 2
解釋: 最長有效括號子串爲 "()"
示例 2:
輸入: ")()())"
輸出: 4
解釋: 最長有效括號子串爲 "()()"
解題思路
個人AC
暴力法
將字符串中的每一個字符作爲首字符來判斷是否爲有效括號序列。
滑動窗口
- 遇到
(
就將其下標放入棧中; - 遇到
)
,先彈出棧頂元素:- 如果棧爲空,則將
(
下標放入棧中; - 如果棧非空,則計算當前
(
的下標與棧頂元素的差值,並更新最大長度;
- 如果棧爲空,則將
- 特別地,可以先在棧中放入
-1
來簡化邏輯。
class Solution {
public int longestValidParentheses(String s) {
int maxLen = 0;
Stack<Integer> stack = new Stack<>(); // 滑動窗口
stack.push(-1);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
stack.push(i);
} else if (c == ')') {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
} else {
maxLen = Math.max(maxLen, i - stack.peek());
}
}
}
return maxLen;
}
}
時間複雜度: ;
空間複雜度: 。
最優解
可以使用額外的變量來替換掉棧,使得空間複雜度可以降爲。
用left
和right
來記錄()
的數量,以尋找最長有效括號序列。
public class Solution {
public int longestValidParentheses(String s) {
int left = 0, right = 0, maxLen = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxLen = Math.max(maxLen, 2 * right);
} else if (right > left) {
left = right = 0;
}
}
// 因爲從左到右遍歷時,最終會出現left > right的情況
// ()(()
left = right = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '(') {
left++;
} else {
right++;
}
if (left == right) {
maxLen = Math.max(maxLen, 2 * left);
} else if (left > right) {
left = right = 0;
}
}
return maxLen;
}
}
時間複雜度: ;
空間複雜度: 。