原題連結在這裡: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.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: " )()()) "
Output: 4
Explanation: The longest valid parentheses substring is "()()"
題解:
這道題是求最長的括号序列,比較容易想到用棧這個資料結構。基本思路就是維護一個棧,遇到左括号就進棧,遇到右括号則出棧,并且判斷目前合法序列是否為最 長序列。不過這道題看似思路簡單,但是有許多比較刁鑽的測試集。具體來說,主要問題就是遇到右括号時如何判斷目前的合法序列的長度。比較健壯的方式如下:
(1) 如果目前棧為空,則說明加上目前右括号沒有合法序列(有也是之前判斷過的);
(2) 否則彈出棧頂元素,如果彈出後棧為空,則說明目前括号比對,我們會維護一個合法開始的起點start, 合法序列的長度即為目前元素的位置 i-start+1; 否則如果棧内仍有元素,那肯定是"(". 合法序列就會從這個"("下一位開始. 長度為目前棧頂元素的位置的下一位到目前元素的距離. i-(stk.peek()+1)+1. 因為棧頂元素後面的括号對肯定是合法的, 而 且左括号出過棧了。
Time Complexity: O(n). Space: O(n).
AC Java:
1 public class Solution {
2 public int longestValidParentheses(String s) {
3 if(s == null || s.length() == 0){
4 return 0;
5 }
6
7 int res = 0;
8 int start = 0;
9
10 Stack<Integer> stk = new Stack<Integer>();
11 for(int i = 0; i<s.length(); i++){
12 if(s.charAt(i) == '('){
13 stk.push(i);
14 }else{
15 //遇到')',但是stack是空的,說明不合法,更新 start 到 i+1
16 if(stk.isEmpty()){
17 start = i+1;
18 }else{
19 //否則彈出棧頂
20 stk.pop();
21 //剩下的stack為空,說明到start 到 i是合法括号對
22 if(stk.isEmpty()){
23 res = Math.max(res, i-start+1);
24 }else{
25 //身下的stack不為空,說明目前stack的棧頂 後面的括号對才是合法的
26 res = Math.max(res, i-stk.peek());
27 }
28 }
29 }
30 }
31 return res;
32 }
33 }
分别計數遇到的"(" 和")"的個數l 和 r. 先從左向右掃, l == r時跟新維護res. 當r大于l 時不合法重置為0.
在反過來從右向左掃一次.
為什麼不能一次呢. e.g. ()((). 中間出現不合法, 若最後及時r比l小, 但取出r*2. 答案就是4. 正解應該是2.
1 class Solution {
2 public int longestValidParentheses(String s) {
3 if(s == null || s.length() == 0){
4 return 0;
5 }
6
7 int res = 0;
8 int l = 0;
9 int r = 0;
10 for(int i = 0; i<s.length(); i++){
11 if(s.charAt(i) == '('){
12 l++;
13 }else{
14 r++;
15 }
16
17 if(l == r){
18 res = Math.max(res, r*2);
19 }else if(r > l){
20 l = 0;
21 r = 0;
22 }
23 }
24
25 l = 0;
26 r = 0;
27 for(int i = s.length()-1; i>=0; i--){
28 if(s.charAt(i) == '('){
29 l++;
30 }else{
31 r++;
32 }
33
34 if(l == r){
35 res = Math.max(res, r*2);
36 }else if(l > r){
37 l = 0;
38 r = 0;
39 }
40 }
41 return res;
42 }
43 }