Leetcode32. Longest Valid Parentheses
关键字:DP,
首先想到的肯定是暴力解法,对每个可能的子字符串进行合法判断,每个子字符串O(n^2),合法判断O(n),加起来O(n^3)。可怕。
就不写了。然后咋改进呢?
自己想到过DP,但是想了想子问题划分,想成了二维dp,没想好怎么划分,就放弃了。
结果看Solution,也是DP。
一维DP,dp[i]表示以i字符结尾的最大Valid Parentheses。
具体看Solution https://leetcode.com/problems/longest-valid-parentheses/solution/
class Solution { public int longestValidParentheses(String s) { if(s==null||s.length()==0) return 0; int[] dp = new int[s.length()]; dp[0] = 0;int max = dp[0]; for(int i=1;i<s.length();i++) { if(s.charAt(i)=='(') dp[i]=0; else { if(s.charAt(i-1)=='(') dp[i]=(i-2>=0?dp[i-2]:0)+2; else { if(i-dp[i-1]-1>=0&&s.charAt(i-dp[i-1]-1)=='(') dp[i]=dp[i-1]+2+(i-dp[i-1]-2>=0?dp[i-dp[i-1]-2]:0); else dp[i]=0; } } max = Math.max(max, dp[i]); } return max; } }
15ms,57.44%,第二个波峰。
然后是一个用栈的做法,因为括号匹配问题很容易想到栈。思路如下:
每次见到一个(,就将他的index入栈,见到一个),就出栈一个元素,直到栈里没有(,则这是这个子字符串的 Longest Valid Parentheses。
然后开始对比下个子字符串即可。
中间涉及到计算长度,所以需要开始push进栈一个-1,后面则push进栈该子字符串的最后一位的index,这样可以通过新子字符串最后一位index和上一个的最后一位index相减算出当前局部max。
具体见代码:
class Solution { public int longestValidParentheses(String s) { int max = 0; Stack<Integer> stack = new Stack<>(); stack.push(-1); for(int i=0;i<s.length();i++){ if(s.charAt(i)=='('){ stack.push(i); } else{ stack.pop(); if(stack.empty()){ stack.push(i); }else{ max = Math.max(max,i-stack.peek()); } } } return max; } }
24ms,15.98%.
虽然很慢,但是做出来了是吧。
看了7ms答案,是dp算法的优化版本:
1 class Solution { 2 public int longestValidParentheses(String s) { 3 if(s==null||s.length()==0) return 0; 4 int max = 0; 5 int[] dp = new int[s.length()]; 6 int opencnt=0; 7 for(int i=0;i<s.length();i++){ 8 if(s.charAt(i)=='(') opencnt++; 9 else{ 10 if(opencnt>0){ 11 dp[i]=dp[i-1]+2; 12 dp[i]+=i>dp[i]?dp[i-dp[i]]:0; 13 max = Math.max(max,dp[i]); 14 opencnt--; 15 } 16 } 17 } 18 return max; 19 } 20 }
思路简化为:仍然是一维DP,简化为有一个虚拟栈的感觉,见到‘(’,虚拟栈多一个元素,只要虚拟栈里有东西,见到‘)’就可以相对dp[i-1]加2。(这里不是dp[i-2]因为前面一个元素也可以是右括号)加2后再对前面的特殊情况做处理。
dp和stack都会即可。如果有空可以看看最快答案,或者试试数组代替stack。

浙公网安备 33010602011771号