LeetCode最長の有効な括弧
@author:Jingdai
@date:2020.10.10
トピックの説明(32の質問)
'('
と')'
文字列のみが含まれている場合、最長の部分文字列を見つけるには、有効な括弧が含まれます。
サンプル入力
")()())"
サンプル出力
4
説明
最长有效括号子串为 "()()"
アイデア
方法1dp
動的計画法では、文字列配列の長さに等しい長さを確立するため
dp[]
に、配列は終了ブラケットの有効長の最長の部分文字列をdp[i]
表しi
ます。
初期条件
明らかに、初期条件
dp[0] = 0
。解決プロセス
いつ
s.charAt(i) == '('
いつdp[i] = 0
。よう
s.charAt(i) == ')'
とs.charAt(i-1) == '('
するときdp[i] = dp[i-2] + 2
。以下に示すように。
As
s.charAt(i) == ')'
ands.charAt(i-1) == ')'
when、ifs.charAt(i-1-dp[i-1]) == '('
、ifdp[i] = dp[i-1] + 2 + dp[i-1-dp[i-1] - 1]
。以下に示すように。予防
境界条件の判断に注意してください。つまり、添え字は境界を越えてはなりません。
以下のコードを参照してください。
方法2スタック
あなたは(私を含め)その前に、有効なブラケットの部分文字列の任意の場所を見つける最初
'('
の数が常に等しくよりも大きい')'
数、そして時に')'
いくつかのより多くの時間、それは確かに有効な文字列のブラケットではありません。このプロパティを使用して、スタックを操作しますstack
。トラバーサル文字列は、満たされ
'('
ている場合、そのインデックスをプッシュします。そうである場合、それとのペアを')'
表す'('
場合があり、スタックが空でない場合はポップされ、有効な文字列を構築するための右角かっこが表示され、有効な部分文字列の長さが添え字の終わりは、現在の添え字からスタックの最上位要素を引いたものです。スタックが空で、')'
さらに表示されている場合は、次の使用として、スタックの現在のインデックスである有効なブラケット文字列になります。ディスカッションの分割ではなく、単一性全体をトラバースするために、-1の最初のプッシュをトラバースする前
')'
に、スタックの最初のプッシュを表します。以下のコードを参照してください。方法3順方向および逆方向の走査
そして、スタックはやや似た考えでした。それは、有効な任意のブラケットのサブストリングであり、その前に(それ自体を含めて)
'('
常に')'
数よりも大きい数であり')'
、それ以上の回数の場合は、確かに有効な文字列ブラケットではありません。まず、頭から弦、録音
left
、right
表現'('
と')'
数字をトラバースします。ときright > left
に不可能があった、それが示す効果的に、ブラケットを訓練left
し、right
トラバースを継続するためにセット0に。の場合left == right
、代表者は有効な括弧の文字列を見つけました。長さを更新します。しかし、これはケース
'('
よりも大きい状況を見逃し')'
ます。たとえば"(()"
、括弧内に有効な文字列が見つからないため、同じ文字列を使用してテールからトラバースするというアイデアは、'('
より多くの時間が経過したときにAであってはなりません。括弧の有効な文字列は、最初のトラバーサルで見逃されたケースを考慮に入れることができます。の場合right < left
、それはleft
、right
トラバースを継続するために0に設定されます。の場合left == right
、代表者は有効な括弧の文字列を見つけました。長さを更新します。以下のコードを参照してください。
コード
方法1
public int longestValidParentheses(String s) { int[] dp = new int[s.length()]; int longestLen = 0; for (int i = 1; i < s.length(); i++) { if (s.charAt(i) == ')') { if (s.charAt(i-1) == '(') { dp[i] = i-2 >= 0 ? (dp[i-2] + 2) : 2; // process when i = 1 longestLen = dp[i] > longestLen ? dp[i] : longestLen; } else if (s.charAt(i-1) == ')' && i-1-dp[i-1] >= 0 && s.charAt(i-1-dp[i-1]) == '(') { if (i-1-dp[i-1]-1 >= 0) { dp[i] = dp[i-1] + 2 + dp[i-1-dp[i-1]-1]; } else { dp[i] = dp[i-1] + 2; } longestLen = dp[i] > longestLen ? dp[i] : longestLen; } } } return longestLen; }
方法2
public int longestValidParentheses(String s) { LinkedList<Integer> stack = new LinkedList<>(); stack.add(-1); int longestLen = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { stack.addFirst(i); } else { stack.poll(); if (stack.size() == 0) { stack.addFirst(i); } else { longestLen = longestLen > i - stack.getFirst() ? longestLen : i - stack.getFirst(); } } } return longestLen; }
方法3
public int longestValidParentheses(String s) { int left = 0; int right = 0; int longestLen = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { left++; } else { right++; } if (left == right) { longestLen = longestLen > 2 * left ? longestLen : 2 * left; } else if (right > left) { left = 0; right = 0; } } left = 0; right = 0; for (int i = s.length() - 1; i >= 0; i--) { if (s.charAt(i) == '(') { left++; } else { right++; } if (left == right) { longestLen = longestLen > 2 * left ? longestLen : 2 * left; } else if (left > right) { left = 0; right = 0; } } return longestLen; }