https://leetcode.com/problems/longest-valid-parentheses/
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.
解题思路:
这是一道比较难的题目,我想了半天也没做出来,参考了其他网友的解法。
这道题类似的Valid Parentheses之前做过,使用了栈的数据结果。思路是,遇到左括号push,遇到右括号pop,如果此时stack空就false,或者整个字符串遍历结束后,stack还有元素就false。
这道题和上面差不多,但是关键在于,如何记录最长的长度?比如"()(())",遍历到最后一个)时候,如何知道这时的长度是从第一位开始,还是第三位?
下面的解法有两处非常巧妙。
第一,用了一个start变量,维护当前位置上的最长长度,可能的左边界。这个边界仅仅在遇到一个右括号,弹出栈内的左括号后,发现栈为空的时候发生。为什么?因为这说明当前已经配对完毕了,从start一直到当前的i,都可以连成一片,中间没有间隔。所以这是长度就是i - start + 1。
第二,遇到左括号push的时候,不是将'('入栈,而是将他的下标push。这样遇到一个右括号,弹出栈内的左括号后,如果stack不为空,就可以先用i - stack.peak()记录当前配对的长度。实际上这个stack.peek()就是之前弹出左括号的前一个下标,所以长度不需要+1了。
如果遇见右括号,而且栈为空呢?说明这个右括号纯粹是多余的,而且无法找到左括号配对了。它将隔断后面所有的配对,所以这时start必须置为i+1。
public class Solution { public int longestValidParentheses(String s) { int length = 0, maxLength = 0, start = 0;; Stack<Integer> stack = new Stack<Integer>(); for(int i = 0; i < s.length(); i++) { if(s.charAt(i) == '(') { stack.push(i); } if(s.charAt(i) == ')') { if(stack.empty()) { start = i + 1; } else { stack.pop(); if(!stack.empty()) { length = i - stack.peek(); maxLength = Math.max(length, maxLength); }else { length = i - start + 1; maxLength = Math.max(length, maxLength); } } } } return maxLength; } }
这道题的思路还是非常巧妙的,有所跳跃,又基于平常的解法,面试的时候如果遇到,还是比较能看出水平的。
update 2015/05/29:
二刷,一个dp的解法,和Valid Parentheses 里的解法一样。
public class Solution { public int longestValidParentheses(String s) { if(s == null || s.length() == 0) { return 0; } int[] dp = new int[s.length()]; dp[0] = 0; for(int i = 1; i < s.length(); i++) { if(s.charAt(i) == '(') { dp[i] = 0; } else { int left = i - 1 - dp[i - 1]; if(left < 0) { dp[i] = 0; } else { if(s.charAt(left) != '(') { dp[i] = 0; } else { if(left > 0) { dp[i] = dp[i - 1] + 2 + dp[left - 1]; } else { dp[i] = dp[i - 1] + 2; } } } } } int max = 0; for(int i = 0; i < dp.length; i++) { max = Math.max(max, dp[i]); } return max; } }
//20180927
class Solution { public int longestValidParentheses(String s) { if (s == null || s.length() == 0 || s.length() == 1) { return 0; } int[] dp = new int[s.length()]; dp[0] = 0; int longest = 0; for (int i = 1; i < s.length(); i++) { if (s.charAt(i) == '(') { dp[i] = 0; } else { int left = i - 1 - dp[i - 1]; if (left < 0 || s.charAt(left) == ')') { dp[i] = 0; } else if (left == 0) { dp[i] = i + 1; } else { dp[i] = dp[left - 1] + i - left + 1; } longest = Math.max(longest, dp[i]); } } return longest; } }