括号问题的标答,用栈解决,但是如果用传统做法,挨个测试字符串的子串是否有效时间复杂度会达到 O ( n 3 ) O(n^3) O(n3),通过不了所有测试用例,于是这道题改了栈的用法,始终保持栈底元素为已遍历元素中最后一个没匹配的右括号下标,但是如果字符串首个字符是‘(’,那么就不满足该条件,因此一开始入栈“-1”元素以保持统一
这道题的具体做法是:
从前往后遍历字符串并更新答案即可
class Solution {
public int longestValidParentheses(String s) {
int n=s.length(),res=0;
if(n<2)
return 0;
Stack<Integer>stack=new Stack<>();
stack.push(-1);
for(int i=0;i<n;i++){
if(s.charAt(i)=='(')
stack.push(i);
else{
stack.pop();
if(!stack.empty())
//当前全部人数减去剩余无法配对的人数(单身)即res
res=Math.max(res,i-stack.peek());
else
stack.push(i);
}
}
return res;
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
困难题怎么能少得了动态规划呢
class Solution {
public int longestValidParentheses(String s) {
int n=s.length(),res=0;
if(n<2)
return 0;
int[] dp=new int[n];
for(int i=1;i<n;i++){
if(s.charAt(i)==')'){
//"()"
if(s.charAt(i-1)=='(')
dp[i]=i-2>=0?dp[i-2]+2:2;
//"))"
else if(s.charAt(i-1)==')'){
//"(...))"
if(i-dp[i-1]-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);
}
}
res=Math.max(res,dp[i]);
}
return res;
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
很巧妙的方法,需要遍历字符串两遍
class Solution {
public int longestValidParentheses(String s) {
int n=s.length(),res=0,left=0,right=0;
if(n<2)
return 0;
//从左向右遍历
for(int i=0;i<n;i++){
if(s.charAt(i)=='(')
left++;
else
right++;
if(left==right)
res=Math.max(res,left+right);
if(right>left){
left=0;
right=0;
}
}
left=right=0;
//从右向左遍历
for(int i=n-1;i>=0;i--){
if(s.charAt(i)=='(')
left++;
else
right++;
if(left==right)
res=Math.max(res,left+right);
if(left>right){
left=0;
right=0;
}
}
return res;
}
}
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)