Valid Parentheses
[!NOTE] This module explores the core principles of the Valid Parentheses problem, deriving solutions from first principles and hardware constraints to build world-class, production-ready expertise.
1. Problem Definition
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
Examples
- Input:
s = "()"→ Output:true - Input:
s = "([)]"→ Output:false - Input:
s = "([])"→ Output:true
Constraints
1 <= s.length <= 10^4sconsists of parentheses only'()[]{}'.
2. Interactive Analysis
Watch how the Stack handles nested structures. Note how the most recently opened bracket must be the first one matched.
({[]})
STACK (LIFO)
3. Solutions
Intuition: The Genesis
The problem is identifying nested dependencies. In any nested structure (HTML tags, JSON, Parentheses), the “most recently opened” context is the “first one closed”. This is the pure definition of LIFO. By using a stack, we effectively “checkpoint” opening brackets and verify them when we see a closing one.
public boolean isValid(String s) {
// ArrayDeque is faster than Stack class (no synchronization overhead)
Deque<Character> stack = new ArrayDeque<>();
for (char c : s.toCharArray()) {
// Map current bracket to its expected closing partner
if (c == '(') stack.push(')');
else if (c == '{') stack.push('}');
else if (c == '[') stack.push(']');
else {
// If it's a closing bracket, it MUST match the top of stack
if (stack.isEmpty() || stack.pop() != c) {
return false;
}
}
}
// Valid only if all "promises" were fulfilled
return stack.isEmpty();
}
func isValid(s string) bool {
// Standard Go slice as a stack
stack := make([]rune, 0)
// Mapping closing to opening for lookup
pairs := map[rune]rune{
')': '(',
'}': '{',
']': '[',
}
for _, char := range s {
if open, isClosing := pairs[char]; isClosing {
// Closing bracket check
if len(stack) == 0 || stack[len(stack)-1] != open {
return false
}
stack = stack[:len(stack)-1] // Pop
} else {
// Opening bracket
stack = append(stack, char)
}
}
return len(stack) == 0
}
4. Complexity Analysis
| Strategy | Time Complexity | Space Complexity | Hardware Connection |
|---|---|---|---|
| Stack (Optimal) | O(N) |
O(N) |
High Cache Locality; uses contiguous memory. |
| Recursive | O(N^2) |
O(N) |
Heavy stack frame overhead for deep nesting. |