Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
For "(()"
, the longest valid parentheses substring is "()"
, which has length = 2.
Another example is ")()())"
, where the longest valid parentheses substring is "()()"
, which has length = 4.
这个题很典型的使用stack来解即可。
想法是存上每个‘(’之前已经匹配的括号数量。
比如
()(()()(()
第1次遇到前括号,入栈数字是0,然后遇到后括号,现在的长度是2+0
第2次遇到前括号,入栈数字是2,当前长度重设为0
第3次遇到前括号,入栈数字是当前长度0.然后后括号,出栈,长度是2+0,
第4次遇到前括号,入栈数字是当前长度2.然后后括号,出栈,长度是2+2,
第5次遇到前括号,入栈数字是当前长度4,当前长度重设为0
第6次遇到前括号,入栈数字是当前长度0,遇到后括号,出栈,长度是2.
如果栈内仍有数字,目前是2,4,则全部出栈,和当前长度2比。取最长为4.
1 public class Solution { 2 public int longestValidParentheses(String s) { 3 // Start typing your Java solution below 4 // DO NOT write main() function 5 Stack<Integer> stack = new Stack<Integer>(); 6 int len = 0; 7 int maxLen = 0; 8 for(int i = 0; i < s.length(); ++i) { 9 if(s.charAt(i) == '(') { 10 stack.push(len); 11 len = 0; 12 } else { 13 if (stack.empty()) { 14 maxLen = Math.max(maxLen, len); 15 len = 0; 16 } else { 17 len = len + 2 + stack.pop(); 18 } 19 } 20 } 21 while(!stack.empty()) { 22 maxLen = Math.max(maxLen, stack.pop()); 23 } 24 return Math.max(maxLen, len); 25 } 26 }
DP 解法:
这道题可以用一维动态规划逆向求解。假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。 dp[i]表示从s[i]到s[s.length - 1]最长的有效匹配括号子串长度, 且这个有效匹配括号一定是从i开始的。则存在如下关系:
1 public int longestValidParentheses(String s) { 2 int n = s.length(); 3 int[] dp = new int[n+1]; 4 int max = 0; 5 for(int i = n-2; i >= 0; i--) { 6 if(s.charAt(i) == '(') { 7 int j = i+1+dp[i+1]; 8 if(j < n && s.charAt(j) == ')') { 9 dp[i] = 2+dp[i+1]+dp[j+1]; 10 max = Math.max(max, dp[i]); 11 } 12 } 13 } 14 15 return max; 16 }
第二遍:使用和 Largest Rectangle in Histogram 类似的思想做。 这里有一个问题 就是如果都规约到了栈空的时候该如何存, 即 () () 这种情况, 所以这时候使用一个变量base。 再就是如果出现了) 而栈里已经没有( 该怎么办。 这时其实出来base 没有和max比较 其他都已经比较了, 所以将base 和 max 比较,然后清空全部东西。
1 public class Solution { 2 public int longestValidParentheses(String s) { 3 // Start typing your Java solution below 4 // DO NOT write main() function 5 if(s == null || s.length() == 0) return 0; 6 Stack<Integer> st = new Stack<Integer>();// 栈里存的是已匹配的最长长度 7 int max = 0; 8 int base = 0; 9 for(int i = 0; i < s.length(); i ++){ 10 if(s.charAt(i) == '('){ 11 st.push(0); 12 }else if(s.charAt(i) == ')' && !st.isEmpty()){//当是)时 进行匹配,消去当前的这一对。并更新最长长度。 13 int tmp = st.pop() + 2; 14 max = tmp > max ? tmp : max; 15 if(!st.isEmpty()){//栈里还有未配对的( 16 st.push(tmp + st.pop()); 17 }else{//栈已经空了,更新base 18 base += tmp; 19 } 20 }else{// )多了 21 max = base > max ? base : max; 22 base = 0; 23 st = new Stack<Integer>(); 24 } 25 } 26 while(!st.isEmpty()){// 查看栈里剩余的那些最长长度, 这些都是没有配对完的。 27 int tmp = st.pop(); 28 max = tmp > max ? tmp : max; 29 } 30 max = base > max ? base : max; 31 return max; 32 } 33 }
第三遍:
先向stack里面放个0 用于都匹配成功的时候存放匹配的个数。
每当遇到( 时, 放一个0, 说明从这个(开始没有匹配成功一对。
每当遇到)时, 如果stack 的 size > 0, 说明还有(没用完,那么进行一次匹配 ==> 将其从stack中取出, 并且将结果加到下一层的(中。
如果 size ==1 ,说明之前所有的(都用完了, 所以重置stack。
1 public class Solution { 2 public int longestValidParentheses(String s) { 3 if(s == null || s.length() == 0) return 0; 4 LinkedList<Integer> ll = new LinkedList<Integer>(); 5 ll.push(0); // this is the bot of the stack(nothing in the stack yet) 6 int max = 0; 7 for(int i = 0; i < s.length(); i ++){ 8 if(s.charAt(i) == '(') ll.push(0); 9 else{ 10 if(ll.size() > 1){ 11 int count = ll.pop(); 12 int sum = count + 1 + ll.pop(); 13 max = max > sum ? max : sum; 14 ll.push(sum); 15 }else{ 16 ll.clear(); 17 ll.push(0); 18 } 19 } 20 } 21 return max * 2; 22 } 23 }
第四遍:
1 public class Solution { 2 public int longestValidParentheses(String s) { 3 if(s == null || s.length() == 0) return 0; 4 LinkedList<Integer> stack = new LinkedList<Integer>(); 5 stack.add(0); 6 int result = 0; 7 for(int i = 0; i < s.length(); i ++){ 8 if(s.charAt(i) == '(') stack.push(0); 9 else{ 10 if(stack.size() > 1){ 11 int tmp = stack.pop() + 2; 12 result = Math.max(result, tmp); 13 tmp += stack.pop(); 14 stack.push(tmp); 15 }else{ 16 int tmp = stack.pop(); 17 result = Math.max(result, tmp); 18 stack.push(0); 19 } 20 } 21 } 22 while(!stack.isEmpty()){ 23 result = Math.max(result, stack.pop()); 24 } 25 return result; 26 } 27 }