题目链接:https://leetcode-cn.com/problems/longest-valid-parentheses/ 题目描述: 给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1: 输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()" 示例 2: 输入: ")()())" 输出: 4 解释: 最长有效括号子串为 "()()"使用栈来存储元素下标,从下标来计算长度。 时间复杂度:O(N),N为字符串长度,遍历每个字符串元素。 空间复杂度:O(N),栈的大小最坏会达到O(N)。
class Solution { public int longestValidParentheses(String s) { int maxans = 0; //栈中存放元素的下标 Deque<Integer> stack = new LinkedList<>(); //栈底存放最新没有匹配的右括号的下标,作为下一个有效括号子串的开端 //将初始化-1入栈,作为下一个有效子串的开端 stack.offerFirst(-1); for(int i=0;i<s.length();i++) { //如果是左括号,就将其下标入栈 if(s.charAt(i) == '(') { stack.offerFirst(i); } //如果是右括号 else { //将栈顶元素出栈 stack.pollFirst(); //如果栈空了,说明这个右括号没有匹配,将其下标入栈 if(stack.isEmpty()) { stack.offerFirst(i); } //如果栈没空,说明是有效子串,计算其最长长度 else { maxans =Math.max(maxans,i - stack.peekFirst()); } } } return maxans; } }动态规划 时间复杂度:O(N) 空间复杂度:O(N)
public class Solution { public int longestValidParentheses(String s) { int[] dp = new int[s.length()]; int result = 0; //记录左括号的数量 int leftCount = 0; for (int i = 0; i < s.length(); i++) { //如果是左括号,计数加1 if (s.charAt(i) == '(') { leftCount++; } //如果是右括号并且leftCount>0 else if (leftCount > 0){ //又有一对括号有效,加2 //dp[i]=dp[i-1]+2 dp[i] = dp[i - 1] + 2; //再找到当前右括号对应的左括号位置之前的位置i-dp[i](如果有的话) //再加上它记录的之前的有效子串的长度 dp[i] += (i - dp[i]) >= 0 ? dp[i - dp[i]] : 0; //结果选择更大的那个 result = Math.max(result, dp[i]); //同时将当前右括号对应的左括号减去,计数-1 leftCount--; } } return result; } }使用两个指针,分别记录左右括号的个数。 两次循环遍历,分别处理右括号多于左括号的情况,和左括号多于右括号的情况,和数量相等为有效子串的情况。 时间复杂度:O(N),空间复杂度:O(1)
class Solution { public int longestValidParentheses(String s) { int res=0; //记录左括号数量 int left=0; //记录右括号数量 int right=0; //正向遍历,处理右括号比左括号多的情况 for(int i=0;i<s.length();i++) { //是左括号,左括号计数加1 if(s.charAt(i) == '(') { left++; } //是有括号,右括号计数加1 else { right++; } //如果左右括号数相等,则是有效括号,计算长度 if(left == right) { res = Math.max(res,2*right); } //如果右括号比左括号多,要重新开始计数 else if(right>left) { left = right = 0; } } //反向再遍历一次,处理左括号比右括号多的情况 left = right = 0; for(int i=s.length()-1;i>=0;i--) { if(s.charAt(i) == '(') { left++; } else { right++; } if(left == right) { res = Math.max(res,2*left); } else if(left > right) { left = right = 0; } } return res; } }