Valid Parentheses

Given a string containing just the characters '(', ')''{''}''[' and ']', determine if the input string is valid.

Example

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

分析:

使用stack来保存每个括号,如果最上面的和当前括号匹配,则除去最上面的括号,否则把新括号加入。如果最后stack为空,则所有括号匹配。

 1 public class Solution {
 2     /**
 3      * @param s A string
 4      * @return whether the string is a valid parentheses
 5      */
 6     public boolean isValidParentheses(String s) {
 7         if (s == null || s.length() % 2 == 1) return false;
 8         Stack<Character> stack = new Stack<Character>();
 9         
10         for (int i = 0; i < s.length(); i++) {
11             if (stack.size() == 0) {
12                 stack.push(s.charAt(i));
13             } else {
14                 char c1 = stack.peek();
15                 char c2 = s.charAt(i);
16                 if (c1 == '(' && c2 == ')' || c1 == '[' && c2 == ']' || c1 == '{' && c2 == '}') {
17                     stack.pop();
18                 } else {
19                     stack.push(s.charAt(i));
20                 }
21             }
22         }
23         return stack.isEmpty();
24     }
25 }

 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.

The idea from https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack

The workflow of the solution is as below.

1. Scan the string from beginning to end. If current character is '(', push its index to the stack. If current character is ')' and the
character at the index of the top of stack is '(', we just find a
matching pair so pop from the stack. Otherwise, we push the index of
')' to the stack.
2. After the scan is done, the stack will only
contain the indices of characters which cannot be matched. Then
 let's use the opposite side - substring between adjacent indices
should be valid parentheses.
3. If the stack is empty, the whole input
string is valid. Otherwise, we can scan the stack to get longest
valid substring as described in step 3.

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         Stack<Integer> st = new Stack<>();
 4         for (int i = 0; i < s.length(); i++) {
 5             if (s.charAt(i) == '(') {
 6                 st.push(i);
 7             } else {
 8                 if (st.empty()) {
 9                     st.push(i);
10                 } else if (s.charAt(st.peek()) == '(') {
11                     st.pop();
12                 } else {
13                     st.push(i);
14                 }
15             }
16         }
17         int longest = 0, end = s.length();
18 
19         while (!st.empty()) {
20             int start = st.pop();
21             longest = Math.max(longest, end - start - 1);
22             end = start;
23         }
24         return Math.max(longest, end);
25     }
26     
27 }

 

Another DP solution (https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack) is also very good. Here is the idea:

First, create an array longest[], for any longest[i], it stores the longest length of valid parentheses which ends at i.

And the DP idea is :

If s[i] is '(', set longest[i] to 0,because any string end with '(' cannot be a valid one.

Else if s[i] is ')'

     If s[i-1] is '(', longest[i] = longest[i-2] + 2

     Else if s[i-1] is ')' and s[i-longest[i-1]-1] == '(', longest[i] = longest[i-1] + 2 + longest[i-longest[i-1]-2]

For example, input "()(())", at i = 5, longest array is [0,2,0,0,2,0], longest[5] = longest[4] + 2 + longest[1] = 6.

 1 int longestValidParentheses(String s) {
 2     if (s.length() <= 1) {
 3         return 0;
 4     }
 5     int curMax = 0;
 6     int[] longest = new int[s.length()];
 7     for (int i = 1; i < s.length(); i++) {
 8         if (s.charAt(i) == ')') {
 9             if (s.charAt(i - 1) == '(') {
10                 longest[i] = (i - 2) >= 0 ? longest[i - 2] + 2 : 2;
11                 curMax = Math.max(longest[i], curMax);
12             } else {
13                 int indexBeforeMatching = i - longest[i - 1] - 1;
14                 if (indexBeforeMatching >= 0 && s.charAt(indexBeforeMatching) == '(') {
15                     longest[i] = longest[i - 1] + 2 + ((i - longest[i - 1] - 2 >= 0) ? longest[i - longest[i - 1] - 2] : 0);
16                     curMax = Math.max(longest[i], curMax);
17                 }
18             }
19         }
20         // else if s[i] == '(', skip it, because longest[i] must be 0
21     }
22     return curMax;
23 }