Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.segmentfault
For "(()", the longest valid parentheses substring is "()", which has length = 2.this
Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.code
時間 O(N) 空間 O(N)orm
用Stack的方法本質上和Valid Parentheses是同樣的,一個右括號能消去Stack頂上的一個左括號。不一樣的是,爲了可以計算括號對的長度咱們還須要記錄括號們的下標。這樣在彈出一個左括號後,咱們能夠根據當前座標減去棧中上一個(也就是Pop事後的Top元素)的座標來獲得該有效括號對的長度。字符串
public class Solution { public int longestValidParentheses(String s) { Stack<Parenthese> stk = new Stack<Parenthese>(); int maxLen = 0; for(int i = 0; i < s.length(); i++){ //遇到左括號,將其push進棧 if(s.charAt(i)=='('){ stk.push(new Parenthese(i, '(')); } else { //遇到右括號,分類討論 //若是當前棧頂是左括號,則消去並計算長度 if(!stk.isEmpty() && stk.peek().symb=='('){ int curLen = 0; stk.pop(); if(stk.isEmpty()){ curLen = i + 1; } else { curLen = i - stk.peek().indx; } maxLen = Math.max(maxLen, curLen); } else { //若是棧頂是右括號或者是空棧,則將右括號也push進棧,它的座標將方便以後計算長度 stk.push(new Parenthese(i, ')')); } } } return maxLen; } public class Parenthese { int indx; char symb; public Parenthese (int i, char s){ this.indx = i; this.symb = s; } } }
時間 O(N) 空間 O(N)get
動態規劃法將大問題化爲小問題,咱們不必定要一會兒計算出整個字符串中最長括號對,咱們能夠先從後向前,一點一點計算。假設d[i]是從下標i開始到字符串結尾最長括號對長度,s[i]是字符串下標爲i的括號。若是s[i-1]是左括號,若是i + d[i] + 1是右括號的話,那d[i-1] = d[i] + 1。若是不是則爲0。若是s[i-1]是右括號,由於不可能有右括號開頭的括號對,因此d[i-1] = 0。string
public class Solution { public int longestValidParentheses(String s) { int[] dp = new int[s.length()]; int maxLen = 0; for(int i = s.length()-2; i >=0; i--){ if(s.charAt(i)=='('){ int end = i + dp[i+1] + 1; if(end < s.length() && s.charAt(end)==')'){ dp[i] = dp[i+1] + 2; if(end + 1 < s.length()){ dp[i] += dp[end + 1]; } } } maxLen = Math.max(maxLen, dp[i]); } return maxLen; } }
Q:可否不用額外空間求解?
A:能夠,可是要提升時間複雜度。好比((()()),先遍歷一遍將全部的()替換成00,獲得((0000),再遍歷一遍,替換全部的(00...00)這種形式字符串爲000...000,這裏咱們獲得(000000,直到遍歷完沒法替換更多括號爲之。若是全部符號都是0,說明是有效的。這樣的時間複雜度是O(N)。io