给出一个长度为 n 的,仅包含字符 '(' 和 ')' 的字符串,计算最长的格式正确的括号子串的长度。
例1: 对于字符串 "(()" 来说,最长的格式正确的子串是 "()" ,长度为 2 .
例2:对于字符串 ")()())" , 来说, 最长的格式正确的子串是 "()()" ,长度为 4 .
字符串长度:
要求时间复杂度 ,空间复杂度 .
"(()"
2
"(())"
4
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here // 固定套路的分类讨论dp // 定义子问题:以i结尾的最长括号字串 // 情况1:以(结尾,就是0 // 情况2:以)结尾,那就到子问题的最长括号的起始位置的前一个位置,看能否有"(" int len = s.length(); int res = 0; int[] dp = new int[len + 1]; for(int i = 1; i <= len; i++) { if(s.charAt(i - 1) == ')' && (i - dp[i - 1] - 2 >= 0) && s.charAt(i - dp[i - 1] - 2) == '(') { dp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2; } res = Math.max(res, dp[i]); } return res; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param s string字符串 * @return int整型 */ // 参考:https://b23.tv/1MZoUWh public int longestValidParentheses (String s) { // write code here // dp[i]表示以s.charAt(i)结尾的最长子括号子串 int[] dp = new int[s.length()]; int max = 0; // 以左括号结尾的dp肯定为0,因此递推公式只需要考虑右括号结尾即可 for (int i = 1; i < s.length(); i++) { // s.charAt(i) == ')'表示s的i位置字符为右括号,右括号才能与i之前的左括号闭合成正确的子串 // i - dp[i - 1] - 1为是与当前右括号闭合的左括号的下标,当前右括号的下标为i,i-1的最长括号 // 子串长度为dp[i-1],则当前右括号闭合的左括号的下标为i - dp[i - 1] - 1。dp[i-1]的值只考虑 // 当前右括号和当前右括号闭合的左括号所夹区域的括号。(i - dp[i - 1] - 1) < 0表示当前右括号 // 无闭合的左括号,即向左去寻找闭合的左括号,寻至首个也首字符也未找到,直至越界,则此时 // 应有dp[i]=0,dp已经初始化为0 // s.charAt(i - dp[i - 1] - 1) == '('表示找到当前右括号闭合的左括号,只有找到闭合的左括号 // dp[i]才能不计为0 if (s.charAt(i) == ')' && (i - dp[i - 1] - 1) >= 0 && s.charAt(i - dp[i - 1] - 1) == '('){ // 2表示当前右括号与左括号的长度。dp[i - 1] 表示以当前右括号的前一个括号结尾的s的长度,即 // 当前右括号和与它闭合的左括号所夹的最长子串长度。dp[i - dp[i - 1] - 2]表示当前右括号的闭合 // 左括号的前一个括号的对应的最长子串长度,越界时计为0 dp[i] =2 + dp[i - 1] + (i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0); } max = Math.max(max, dp[i]); } return max; } }
public int longestValidParentheses (String s) { //长度:当前索引-栈顶索引 Stack<Integer> st=new Stack<>(); st.push(-1);//避免第一个是),造成异常,初始化栈顶为- int ans=0; for(int i=0;i<s.length();i++){ if(s.charAt(i)=='('){//栈记录左括号下标,左括号入栈 st.push(i); }else{ st.pop();//遇到右括号,弹出左括号下标 if(st.isEmpty()){//栈为空,记录上一次结束的位置 st.push(i); }else{//栈不空,说明栈中还有左括号,右括号不够用,减去栈顶位置就是长度 ans=Math.max(ans,i-st.peek());//长度更新为:当前下标和栈顶下标的距离 (括号长度) } } } return ans; }
import java.util.*; public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here // 单序列问题,每一位存储以当前位置结尾的最长子串长度 if(s.length()<=1)return 0; int len=s.length(); int[] dp=new int[len]; int l=0; int res=0; Stack<Integer> stack=new Stack(); while(l<len){ // 如果当前是左括号,入栈 if(s.charAt(l)=='('){ stack.push(l); l++; } else{ // 如果是右括号,出栈 if(stack.isEmpty()){ l++; } else{ int top=stack.pop(); dp[l]=l-top+1; if(top>0){ dp[l]+=dp[top-1]; } res=Math.max(res,dp[l]); l++; } } } return res; } }其实不需要记录连续括号上次结束位置的
public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { int len = s.length(); if(len == 0){ return 0; } // 定义dp, dp[i] = 当前0 ~ i个字符,有效括号的长度 int[] dp = new int[len]; char[] chars = s.toCharArray(); // 字符数组 int result = 0; // 返回值 int pre = -1; // 指向 // 遍历字符数组,从1开始,因为0位置无论是左括号 还是 右括号,能组成的有效括号长度都是0 for (int i = 1; i < chars.length; i++) { // i只匹配右括号,遇到左括号它并不能组成括号,所以忽略 if(chars[i] == ')'){ // 当i是 ) 时,需要看 i - 1 位置的有效括号长度是多少, // 假设此时i = 3, i-1的位置 在dp中记录的有效长度是2, // 那么需要向前看 i - 2 - 1位置,也就是i-1有效长度的再前一个位置的结果 pre = i - dp[i - 1] - 1; // 如果这个pre不越界,并且在char数组中等于( ,那么说明它能跟当前i字符) 匹配成一个有效括号 if(pre >= 0 && chars[pre] == '('){ // 那么dp[i] 的有效括号长度,最起码是 dp[i-1] + 2 // 但还需要再累加上 pre-1的索引在dp记录的有效长度,如果越界则累加0,如果不越界,则累加dp[pre - 1] dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0); } } // 每次循环都将dp[i] 与 result 取最大值 result = Math.max(result, dp[i]); } // 循环结束,result为解 return result; } }
import java.util.*; public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here int[] dp = new int[s.length()+1]; LinkedList<Integer> stack = new LinkedList(); int maxNum = 0; for(int i=1;i<s.length()+1;i++){ if(s.charAt(i-1)=='('){ stack.addLast(i); } else if(!stack.isEmpty()){ int left = stack.removeLast(); dp[i] = i - left + 1; dp[i] += dp[left-1]; } maxNum = Math.max(maxNum, dp[i]); } return maxNum; } }
import java.util.*; public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here Deque<Integer> stack = new ArrayDeque<>(); int n = s.length(); int[] flag = new int[n]; for (int i = 0; i < n; i++) { if (s.charAt(i) == '(') stack.push(i); else { if (stack.isEmpty()) flag[i] = 1; else stack.pop(); } } while (!stack.isEmpty()) { flag[stack.pop()] = 1; } int res = 0, l = 0; for (int i = 0; i < n; i++) { if (flag[i] == 1) { l = 0; continue; } l++; res = Math.max(res, l); } return res; } }
import java.util.*; public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here if(s.length()==0){return 0;} if(s.length()==1){return 0;} Deque<Integer> stack=new LinkedList<Integer>(); ArrayList<Integer> list=new ArrayList<Integer>(); for(int i=0;i<=s.length()-1;i++){ char c=s.charAt(i); if(c=='('){stack.push(i);} if(c==')'){ if(!stack.isEmpty()){ list.add(stack.pop()); list.add(i); } } } return max_length(list); } public int max_length(ArrayList<Integer> list){ if(list.isEmpty()){return 0;} Collections.sort(list); int[] arr=new int[list.size()]; for(int i=0;i<=list.size()-1;i++){ arr[i]=list.get(i); } int[] dp=new int[arr.length]; dp[0]=1; for(int i=1;i<=arr.length-1;i++){ if(arr[i-1]==arr[i]-1){ dp[i]=dp[i-1]+1; }else{ dp[i]=1; } } int max=dp[0]; for(int i=0;i<=dp.length-1;i++){ max=dp[i]>max?dp[i]:max; } return max; } }
import java.util.*; public class Solution { /** * * @param s string字符串 * @return int整型 */ public int longestValidParentheses (String s) { // write code here int len = s.length(); if(len == 0) return 0; int max = 0; int l = 0 , r = 0; for(int i = 0; i < len; i++){ if(s.charAt(i) == '('){ l++; } if(s.charAt(i) == ')'){ r++; } if(l == r){ max = max > 2 * r ? max : 2 * r; } if(l < r){ l = 0; r = 0; } } l = 0; r = 0; for(int i = len - 1; i >= 0 ;i--){ if(s.charAt(i) == '('){ l++; } if(s.charAt(i) == ')'){ r++; } if(l == r){ max = max > 2 * r ? max : 2 * r; } if(l > r){ l = 0; r = 0; } } return max; } }
public int longestValidParentheses(String s) { if (s == null || s.length() < 2) { return 0; } int[] dp = new int[s.length()]; if (s.charAt(0) == '(' && s.charAt(1) == ')') { dp[1] = 2; } int res = Math.max(dp[1], 0); for (int i = 2; i < s.length(); i++) { if (s.charAt(i) == ')') { if (s.charAt(i - 1) == '(') { dp[i] = 2 + dp[i - 2]; } else { int index = i - dp[i - 1] - 1; if (index >= 0 && s.charAt(index) == '(') { dp[i] = 2 + dp[i - 1]; if (index - 1 >= 0) { dp[i] += dp[index - 1]; } } } } res = Math.max(res, dp[i]); } return res; }
int max=0,n=s.length(); int[]dp=new int[n];//dp[i]表示以i结尾的括号子串的长度 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; } else{ //如果j=i-dp[i-1]-1位置(也就是dp[i-1]括号字串的前一个元素)是'(',则增加了匹配长度 //那么扩展之后的字串长度=dp[i-1]的长度+2+dp[j-1]位置匹配的长度 int j=i-dp[i-1]-1; if(j>=0&&s.charAt(j)=='('){ dp[i]=dp[i-1]+(j-1>=0?dp[j-1]:0)+2;//2是i位置的)和j位置的(匹配的 } } } max=Math.max(max,dp[i]); } 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; } }