给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”
思路与代码
动态规划
我们定义dp[i]
表示以下标 i
字符结尾的最长有效括号的长度。我们将 dp
数组全部初始化为 0
。显然有效的子串一定以 ')'
结尾,因此我们可以知道以 '('
结尾的子串对应的 dp
值必定为 0
,我们只需要求解 )
在 dp
数组中对应位置的值。
由下图可得转移方程:
如果i-dp[i-1]-1 >= 0 && s.charAt(i-dp[i-1]-1) == '('
则 dp[i] = 2 + dp[i-1] + dp[i - dp[i-1] -2]
由三段组成 (注意判断下标i - dp[i-1] -2
是否越界)
否则 dp[i] = 0
class Solution {
public int longestValidParentheses(String s) {
int maxLen = 0;
int[] dp = new int[s.length()];
for (int i = 1; i < s.length(); i++){
if (s.charAt(i) == ')'){
if (i-1 - dp[i-1] >= 0 && s.charAt(i-1 - dp[i-1]) == '('){
dp[i] = 2 + dp[i-1];
if (i-2 - dp[i-1] >= 0)
dp[i] += dp[i-2 - dp[i-1]];
}
maxLen = Math.max(maxLen, dp[i]);
}
}
return maxLen;
}
}
基于栈
- 对于遇到的每个
‘(’
,我们将它的下标放入栈中 - 对于遇到的每个
‘)’
,我们先弹出栈顶元素表示匹配了当前右括号:- 如果栈为空,说明当前的右括号为没有被匹配的右括号,我们将其下标放入栈中来更新我们之前提到的「最后一个没有被匹配的右括号的下标」
- 如果栈不为空,当前右括号的下标减去栈顶元素即为「以该右括号为结尾的最长有效括号的长度」
class Solution {
public int longestValidParentheses(String s) {
int maxLen = 0;
Deque<Integer> deque = new LinkedList();
deque.push(-1);
for (int i = 0; i < s.length(); i++){
if (s.charAt(i) == '(')
deque.push(i);
else{
deque.pop();
if (deque.isEmpty()) deque.push(i);
else maxLen = Math.max(maxLen, i - deque.peek());
}
}
return maxLen;
}
}