Longest Valid Parentheses
Master this topic with zero to advance depth.
Longest Valid Parentheses
Given a string containing just the characters '(' and ')', return the length of the longest valid (well-formed) parentheses substring.
Visual Representation
s = ")()())"
Substrings:
() -> 2
()() -> 4 (Max)
DP Strategy:
dp[i] = length of longest valid parentheses ending at index i.Examples
The longest valid parentheses substring is "()".
The longest valid parentheses substring is "()()".
Level I: Dynamic Programming
Intuition
We use a 1D DP array where dp[i] is the length of the longest valid parentheses ending at index i.
Thought Process
- If
s[i] == '(',dp[i] = 0(valid substring can't end with open paren). - If
s[i] == ')':- If
s[i-1] == '(', thendp[i] = dp[i-2] + 2. - If
s[i-1] == ')'ands[i - dp[i-1] - 1] == '(', thendp[i] = dp[i-1] + dp[i - dp[i-1] - 2] + 2.
- If
- Keep track of maximum
dp[i].
Detailed Dry Run
s = "()()"
| i | char | Calculation | dp[i] |
|---|---|---|---|
| 0 | ( | - | 0 |
| 1 | ) | dp[0-1]+2 = 2 | 2 |
| 2 | ( | - | 0 |
| 3 | ) | dp[3-2]+2 = dp[1]+2 = 4 | 4 |
Level II: Stack-Based Approach
Intuition
Use a stack to track unmatched parenthesis indices. Whenever we find a matching pair, the valid length is i - stack.peek().
Visual
s = ")()())"
stack: [-1]
i=0 ')': stack = [] -> push 0? No, stack is empty -> push i=0
i=1 '(': stack = [0, 1]
i=2 ')': pop 1 -> stack = [0], len = 2-0=2
i=3 '(': stack = [0, 3]
i=4 ')': pop 3 -> stack = [0], len = 4-0=4
i=5 ')': pop 0 -> stack = [], push 5
Max = 4Detailed Dry Run
s="())". stack=[-1]. i=0 '(': push 0. i=1 ')': pop 0, len=1-(-1)=2, max=2. i=2 ')': pop -1, empty -> push 2. Result = 2.
⚠️ Common Pitfalls & Tips
Initialize the stack with -1 as a sentinel base index. Without this, first close parenthesis would fail to compute length (0 - nothing = invalid).
Level III: Two Counters (Optimal Space)
Intuition
We can optimize space to O(1) by scanning the string twice (left-to-right and right-to-left) while keeping track of left and right parentheses counts.
Logic Steps
- Scan Left to Right:
left++for '(',right++for ')'.- If
left == right, current length is2 * left. Updatemax. - If
right > left, reset both to 0.
- Scan Right to Left:
- Repeat same logic but reset if
left > right.
- Repeat same logic but reset if
Detailed Dry Run
s = "(()"
- L-R: '('(L1,R0), '('(L2,R0), ')'(L2,R1). L!=R. Max=0.
- R-L: ')'(L0,R1), '('(L1,R1) -> Max=2, '('(L2,R1) -> Reset. Result: 2.
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.