题目
这道题需要仔细审题,开始的时候就做错了好几次,因为题目意思理解错了,理解成一个有效的括号最长为多少,或者有多少对匹配的字符串之类的。
思路一:栈
想要获取匹配括号的长度,应该是‘)’的下标,减去‘(’的前一个的下标。
所以提前入栈-1.
如果遇到‘(’,将下标入栈
如果遇到‘)’,将栈顶元素出栈,如果栈为空,则将该元素入栈,否则括号的最长长度为(当前元素下标-栈顶元素)与目前最长长度相比的最大值。
ans = Math.max(ans,i-stack.peek());
具体代码
class Solution {
public int longestValidParentheses(String s) {
if(s == null && s.length()==0){
return 0;
}
Stack<Integer> stack = new Stack<>();
stack.push(-1);
int ans = 0;
for(int i = 0;i < s.length();i++){
if(s.charAt(i) == '('){
stack.push(i);
}else{
stack.pop();
if(stack.isEmpty()){
stack.push(i);
}else{
ans = Math.max(ans,i-stack.peek());
}
}
}
return ans;
}
}
时间复杂度:O(n)
空间复杂度:O(n)
思路二:
用left记录‘(’的个数,用right记录‘)’的个数,
从左往右遍历
如果两者相等,则长度为2left(或right)
如果right>left,则left=right=0;
从右往左遍历
如果两者相等,则长度为2left(或right)
如果left>right,则left=right=0;
具体代码
class Solution {
public int longestValidParentheses(String s) {
int left = 0;
int right = 0;
int ans = 0;
for(int i = 0;i < s.length();i++){
if(s.charAt(i)=='('){
left++;
}
else if(s.charAt(i)==')'){
right++;
}
if(left == right){
ans = Math.max(ans,2*left);
}else if(right > left){
left = right = 0;
}
}
left = right = 0;
for(int i = s.length()-1;i >= 0;i--){
if(s.charAt(i)==')'){
right++;
}else{
left++;
}
if(left == right){
ans = Math.max(ans,2*left);
}else if(left > right){
left = right = 0;
}
}
return ans;
}
}
思路三:动态规划
dp[i]表示下标为i时有效括号长度。
从左往右遍历,遇到‘)’,判断前一个字符是不是‘(’,
若是:
如果i-2>=0,那么dp[i] = dp[i-2]+2;
否则:dp[i] = 2;
若前一个字符是‘)’,则判断下标i-i-dp[i-1]-1是否存在,该位置的字符是不是‘(’,
若是,i-i-dp[i-1]-2是否大于等于0,是则
dp[i] = dp[i-1]+dp[i-dp[i-1]-2]+2;
否则,
dp[i] = dp[i-1]+2;
具体代码
class Solution {
public int longestValidParentheses(String s) {
if(s == null || s.length()==0){
return 0;
}
int[] dp = new int[s.length()];
int max = 0;
dp[0] = 0;
for(int i = 1;i < s.length();i++){
if(s.charAt(i) == '('){
dp[i] = 0;
}else{
if(s.charAt(i-1)=='('){
dp[i] = i-2>=0?dp[i-2]+2:2;
}else if(i - dp[i-1]-1>=0&&s.charAt((i - dp[i-1]-1))=='('){
dp[i] = i-dp[i-1]-2>=0?dp[i-1]+dp[i-dp[i-1]-2]+2:dp[i-1]+2;
}
}
max = Math.max(max,dp[i]);
}
return max;
}
}