给出一个长度为 n 的,仅包含字符 '(' 和 ')' 的字符串,计算最长的格式正确的括号子串的长度。
例1: 对于字符串 "(()" 来说,最长的格式正确的子串是 "()" ,长度为 2 .
例2:对于字符串 ")()())" , 来说, 最长的格式正确的子串是 "()()" ,长度为 4 .
字符串长度:
要求时间复杂度
,空间复杂度
.
"(()"
2
"(())"
4
/*
* 非动态规划,有时候会超时
*/
public int longestValidParentheses(String s) {
if (s == null || s.length() < 1)
return 0;
Stack<Integer> stack = new Stack<Integer>();
int max = 0, left = -1;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(')
stack.push(i);
else {
if (!stack.isEmpty()) {
stack.pop();
if (!stack.isEmpty())
max = Math.max(max, i - stack.peek());
else
max = Math.max(max, i - left);
} else
left = i;
}
}
return max;
}
// Your runtime beats 92.48 % of java submissions.
public int longestValidParentheses2(String s) {
if (s == null || s.length() == 0)
return 0;
int[] dp = new int[s.length()];
int ans = 0;
for (int i = 1; i < s.length(); i++) {
// 如果是'('直接跳过,默认为0
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(')
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
// 说明s.charAt(i - 1)==')'
else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
dp[i] = (i - dp[i - 1] > 1 ? dp[i - dp[i - 1] - 2] : 0) + dp[i - 1] + 2;
// 因为加了一个左括号和一个右括号,所以是加2
}
}
ans = Math.max(ans, dp[i]);
}
return ans;
}
//维护一个栈,里面保存'('的下标,每次进入一个')'时,栈弹出,ans更新为当前扫描的下标
//与栈顶元素之间的距离(因为中间可能有些括号已经被消掉了),因为栈可能为空,所以需要
//记录下起始记录点last。
class Solution {
public:
int longestValidParentheses(string s) {
int ans=0,last=-1;
stack<int> st;
for(int i=0;i<s.size();i++){
if(s[i]=='(') st.push(i);
else{
if(!st.size()) last=i;
else{
st.pop();
if(st.size()) ans=max(ans,i-st.top());
else ans=max(ans,i-last);
}
}
}
return ans;
}
}; class Solution(object):
def longestValidParentheses(self, s):
res = 0
stack = []
prev = 0
for i in range(len(s)):
if s[i] == "(":
stack.append(i - prev)
prev = 0
else:
if len(stack) > 0:
prev = i - stack.pop() + 1
res = max(res, prev)
else:
prev = 0
return res public static int longestValidParentheses(String s) {
if (s.length() == 0) return 0;
int left = 0;
int right = 0;
int maxLength = 0;
//从左边遍历,左括号则left加1,有括号则right加1
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '('){
left++;
}else {
right++;
}
//left和right相等则最大值为left,
if (left == right){
maxLength = Math.max(maxLength,left);
}else if(left < right){ //如果left小于了right则证明不连续了,将left和right置位0
left = 0;
right = 0;
}
}
left = 0;
right = 0;
//同样的道理,从右往左倒序遍历一次,左括号则left加1,有括号则right加1
for (int i = s.length()-1; i >= 0; i--) {
if (s.charAt(i) == '('){
left++;
}else {
right++;
}
//left和right相等则最大值为left,
if (left == right){
maxLength = Math.max(maxLength,left);
}else if(left > right){//如果left大于了right则证明不连续了,将left和right置位0
left = 0;
right = 0;
}
}
return maxLength*2;
} int longestValidParentheses(string s)
{
stack<int> sta; int count = 0, max_len = 0; bool fflag = true;
for (int i = 0; i < s.size(); ++i)
{
if (!sta.empty() && s[i] == ')' && s[sta.top()] == '(')
{
sta.pop();
}
else
{
sta.push(i);
}
}
if (sta.empty()) return s.size();
count = s.size();
while (!sta.empty())
{
count = count - sta.top() - 1;
max_len = max(count, max_len);
count = sta.top();
sta.pop();
}
max_len = max(count, max_len);
return max_len;
} 思路:
初始化一个栈,每遇到左括号 那么将该左括号下标入栈
遇到右括号时,如果栈中包含左括号,那么这一组括号完成匹配,在对应dp数组位置标记为true
最后遍历dp数组 找到最长的true长度即为 最长的符合括号匹配条件的长度。
bool can[100000];//将遍历过程中 合法的括号位置标记为true int longestValidParentheses(string s) { // write code here if(s.size()==0) return 0; for(int i=0;i<s.size();i++) can[i]=false; stack<int> my_stack; for(int i=0;i<s.size();i++) { if(s[i]=='(') //左括号 那么Index入栈 my_stack.push(i); else { if(!my_stack.empty()) //栈非空 { can[i]=true; can[my_stack.top()]=true; my_stack.pop();//弹出 } } } //找到can中最长的连续true长度即可 int _max=0; int i=0; for(;i<s.size();i++) { int num=0; while(i<s.size() && can[i]==true) { i++; num++; } _max=max(_max,num); } return _max; }
import java.util.*;
public class Solution {
/**
*
* @param s string字符串
* @return int整型
*/
public int longestValidParentheses (String s) {
// write code here
Stack<Integer> stack=new Stack<>();
int max=0;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='(')
stack.push(i);
else{
if(stack.size()==0)
stack.push(i);
else{
int top=stack.peek();
if(s.charAt(top)=='('){
stack.pop();
if(stack.size()==0){
max=i+1;
}
else{
max=max>i-stack.peek()?max:i-stack.peek();
}
}
else{
stack.push(i);
}
}
}
}
return max;
}
} /*很多人会说这道题用动规,可是用动规每次匹配后还要向前到上一个匹配跟这个匹配是否连接,时间复杂度为O(n^2),其实可以换个想法,用一个bool数组来标记已经匹配过的字符,找到最长的连续标记的长度就是所求的结果。只要遍历两遍数组,时间复杂度为O(n)*/ import java.util.*;
public class Solution {
public int longestValidParentheses(String s) {
if(s.length() == 0){
return 0;
}
boolean[] f = new boolean[s.length()];
char[] chs = s.toCharArray();
Stack<Integer> stack = new Stack<>();
int index = -1,max = 0;
for(int i =0;i<chs.length;i++){
if(chs[i] == '('){
stack.push(i);
}else{
if(!stack.empty()){
f[i] = true;
int t = stack.pop();
f[t] = true;
}
}
}
index = 0;
for(int i = 0;i<chs.length;i++){
if(f[i]){
index++;
max = max>index?max:index;
}else{
index =0;
}
}
return max;
}
}
class Solution:
def longestValidParentheses(self , s ):
if s == "":return 0
pre = 0
end = 0
for i in range(len(s)):
if s[i]=='(':pre+=1
elif (s[i]==')') and (pre>0):
pre-=1
end+=2
return end class Solution {
public:
int longestValidParentheses(string s) {
int l = s.length(); if(s == "" || l<=0) return 0; stack<int> S; int Max = 0; int t = -1; for(int i=0;i<l;i++) { if(s[i] == '(') S.push(i); else{ if(S.empty()) t = i; else{ S.pop(); if(S.empty()) Max = max(Max, i - t); else Max = max(Max, i - S.top()); } } } return Max;
}
};
import java.util.Stack;
public class Solution {
public int longestValidParentheses(String s) {
if(s == null || s.length() <= 0)
return 0;
// stack中保存左括弧的index
Stack<Integer> stack = new Stack<>();
int maxLen = 0;
int last = -1;
for(int i = 0; i < s.length(); i++){
// 遇到左括弧就压栈
if(s.charAt(i) == '(')
stack.push(i);
else{
// 栈为空,更新起始点的位置
if(stack.isEmpty())
last = i;
else{
stack.pop();
// 更新合法括弧的长度
if(stack.isEmpty())
maxLen = Math.max(maxLen, i - last);
else
maxLen = Math.max(maxLen, i - stack.peek());
}
}
}
return maxLen;
}
}
int longestValidParentheses(string s) {
int Max=0,Sum=0;
stack<char> S;
for(int i=0;i<s.length();i++){
if(s[i]==')'){
if(S.empty()){Sum=0;}
else{
S.pop();
Sum+=2;
Max = max(Max,Sum);
}
}
else{
S.push('(');
}
}
return Max;
} import java.util.*;
public class Solution {
public int longestValidParentheses (String s) {
Stack<Integer> stack = new Stack<>(); // 设定栈,存储左括号
stack.push(-1); // 压入-1,处理边界问题
int res = 0; // 结果存储变量
for (int i = 0;i < s.length();i++) {
// 如果是左括号则直接入栈
if (s.charAt(i) == '(') {
stack.push(i);
}else {
// 如果是右括号,则弹栈
stack.pop();
// 判空,若栈为空,则说明i左侧已经没有可用的左括号,此时将i压入栈中,防止空栈异常
if (stack.isEmpty()) {
stack.push(i);
}else {
// 长度计算时无需加1,因为预先弹栈,相当于已经加过1,且在01边界上因为初始化时压入-1进栈,因此也得以解决
res = Math.max(res, i - stack.peek());
}
}
}
return res;
}
} class Solution {
public:
/**
*
* @param s string字符串
* @return int整型
*/
int longestValidParentheses(string s) {
// 时间复杂度O(N),空间复杂度O(N)
int res = 0, start = -1;
stack<int> stk;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') stk.push(i);
else {
if (stk.empty()) start = i;
else {
stk.pop();
if (!stk.empty()) res = max(res, i - stk.top());
else res = max(res, i - start);
}
}
}
return res;
}
}; //用动态规划做速度更快
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size(), res = 0;
vector<int> dp(n + 1, 0);//dp[i]表示以当前位置为终点的最长长度,则只能在)处更新
dp[0] = dp[1] = 0;
for(int i = 2; i <= n; i++){
if(s[i - 1] == ')'){
//如果s[i-2-dp[i-1]]=='(',则说明当前位置可以和i-2-dp[i-1]位置匹配,dp[i]=dp[i-1]+2
if(s[i - 2 - dp[i - 1]] == '(') dp[i] = dp[i - 1] + 2;
dp[i] += dp[i - dp[i]];//还要加上匹配位置之前的最长长度dp[i]+=dp[i-dp[i]]
}
res = max(res, dp[i]);
}
return res;
}
};