|
| 1 | +# Longest Valid Parentheses |
| 2 | +[LeetCode Problem]https://leetcode.com/problems/longest-valid-parentheses/description/ |
| 3 | + |
| 4 | +Given a string containing just the characters '(' and ')', return the length of the longest valid (well-formed) parentheses substring. |
| 5 | + |
| 6 | +## Example 1 |
| 7 | +``` |
| 8 | +Input: s = "(()" |
| 9 | +Output: 2 |
| 10 | +Explanation: The longest valid parentheses substring is "()". |
| 11 | +``` |
| 12 | + |
| 13 | +## Example 2: |
| 14 | +``` |
| 15 | +Input: s = ")()())" |
| 16 | +Output: 4 |
| 17 | +Explanation: The longest valid parentheses substring is "()()". |
| 18 | +``` |
| 19 | + |
| 20 | +## Example 3: |
| 21 | +``` |
| 22 | +Input: s = "" |
| 23 | +Output: 0 |
| 24 | +``` |
| 25 | + |
| 26 | +### Constraints: |
| 27 | +```javascript |
| 28 | +0 <= s.length <= 3 * 104 |
| 29 | +s[i] is '(', or ')' |
| 30 | +``` |
| 31 | + |
| 32 | +## Approach: |
| 33 | +One of the key things to realize about valid parentheses strings is that they're entirely self-satisfied, meaning that while you can have one substring that is entirely inside another, you can't have two substrings that only partially overlap. |
| 34 | + |
| 35 | +This means that we can use a greedy O(N) time complexity solution to this problem without the need for any kind of backtracking. In fact, we should be able to use a very standard stack-based valid parentheses string algorithm with just three very minor modifications. |
| 36 | + |
| 37 | +In a stadard valid parentheses string algorithm, we iterate through the string (S) and push the index (i) of any '(' to our stack. Whenever we find a ')', we match it with the last entry on the stack and pop said entry off. We know the string is not valid if we find a ')' while there are no '(' indexes in the stack with which to match it, and also if we have leftover '(' in the stack when we reach the end of S. |
| 38 | + |
| 39 | +For this problem, we will need to add in a step that updates our answer (ans) when we close a parentheses pair. Since we stored the index of the '(' in our stack, we can easily find the difference between the ')' at i and the last entry in the stack, which should be the length of the valid substring which was just closed. |
| 40 | + |
| 41 | +But here we run into a problem, because consecutive valid substrings can be grouped into a larger valid substring (ie, '()()' = 4). So instead of counting from the last stack entry, we should actually count from the second to last entry, to include any other valid closed substrings since the most recent '(' that will still remain after we pop the just-matched last stack entry off. |
| 42 | + |
| 43 | +This, of course, brings us to the second and third changes. Since we're checking the second to last stack entry, what happens in the case of '()()' when you close the second valid substring yet there's only the one stack entry left at the time? |
| 44 | + |
| 45 | +To avoid this issue, we can just wrap the entire string in another imaginary set of parentheses by starting with stack = [-1], indicating that there's an imaginary '(' just before the beginning of the string at i = 0. |
| 46 | + |
| 47 | +The other issue is that we will want to continue even if the string up to i becomes invalid due to a ')' appearing when the stack is "empty", or in this case has only our imaginary index left. In that case, we can just effectively restart our stack by updating our imaginary '(' index (stack[0] = i) and continue on. |
| 48 | + |
| 49 | +Then, once we reach the end of S, we can just return ans. |
| 50 | + |
| 51 | +## Problem Added By |
| 52 | + |
| 53 | +- [himanshukoshti](https://github.com/himanshukoshti) |
| 54 | + |
| 55 | + |
| 56 | + |
| 57 | +## Contributing |
| 58 | +Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. |
| 59 | + |
| 60 | +Please make sure to update tests as appropriate. |
0 commit comments