leetcode32-最长有效括号
- dp
dp[i]
表示以i为结尾的有效括号的最大长度,dp转移方程如下:
- 如果i是
)
且i-1是(
,那么dp[i] = dp[i-2]+2
- 如果i是
)
且i-1是)
,且第i-dp[i-1]-1
是(
,这样刚好能和第i个字符进行匹配。那么dp[i] = dp[i-dp[i-1]-2] + (i+1-(i-dp[i-1]-1))
即dp[i-dp[i-1]-2]+dp[i-1]+2
。其中本段的长度为dp[i-1]+2
,之前的部分长度为dp[i-dp[i-1]-2]
,可以与本段进行拼凑。
class Solution {
public int longestValidParentheses(String s) {
int n = s.length(), dp[] = new int[n], max = 0;
for(int i = 1; i < n; i++){
if(s.charAt(i) == ')'){
if(s.charAt(i-1) == '(') dp[i] = i >= 2 ? dp[i-2]+2 : 2;
else if(i-dp[i-1] > 0 && s.charAt(i-dp[i-1]-1) == '(')
dp[i] = dp[i-1]+2 + (i - dp[i-1] >= 2 ? dp[i-dp[i-1]-2] : 0);
max = Math.max(max, dp[i]);
}
}
return max;
}
}
- 栈
使用栈记录上一次匹配成功的位置。初始在栈中放入-1。
如果字符为(,那么直接放入栈中;如果字符为),那么需要将栈顶的元素pop出来。pop之后一旦堆栈为空,则需要将当前位置放入堆栈(堆栈为空则意味着本次匹配是个无效匹配,右括号多出一个,需要重新标记上次的下标)。然后本次的长度就是当前的坐标减去栈顶的元素
class Solution {
public int longestValidParentheses(String s) {
Deque<Integer> stk = new ArrayDeque<>();
int max = 0;
stk.push(-1);
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == '(') stk.push(i);
else{
stk.pop();
if(stk.isEmpty()) stk.push(i);
max = Math.max(max, i-stk.peek());
}
}
return max;
}
}
- 只记录左括号和右括号的数量
不需要维护dp数据或者栈,只去记录左括号和右括号的数量
当左括号和右括号数量相等时,更新最大值。当右括号的数量大于左括号的时候,说明在此之前的括号无法匹配,清空左右括号数量。
但是这时候有个问题,就是如果左括号的数量一直大于右括号,那么就一直无法更新最大值,所以需要从右向左再次进行遍历,规则相反。
class Solution {
public int longestValidParentheses(String s) {
int max = 0, left = 0, right = 0, n = s.length();
for(int i = 0; i < n; i++){
if(s.charAt(i) == '(') left++;
else right++;
if(left == right) max = Math.max(max, 2*left);
else if(right > left) left = right = 0;
}
left = right = 0;
for(int i = n-1; i >= 0; i--){
if(s.charAt(i) == ')') right++;
else left++;
if(left == right) max = Math.max(max, 2*left);
else if(left > right) left = right = 0;
}
return max;
}
}
本文作者:xzh-yyds
本文链接:https://www.cnblogs.com/xzh-yyds/p/16597377.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步