Valid Parentheses
Determine if the input string with parentheses is valid using stack-based methods.
๐งฉ Problem Statement
Given a string containing just the characters โ(โ, โ)โ, โ{โ, โ}โ, โ[โ, and โ]โ, determine if the input string is valid.
A string is valid if:
- Open brackets are closed by the same type of brackets.
- Open brackets are closed in the correct order.
โ๏ธ Function Signature
public boolean isValid(String s)
๐ Approach: Using Stack
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '{' || c == '[') {
stack.push(c);
} else if (!stack.isEmpty() &&
((c == ')' && stack.peek() == '(') ||
(c == '}' && stack.peek() == '{') ||
(c == ']' && stack.peek() == '['))) {
stack.pop();
} else {
return false;
}
}
return stack.isEmpty();
}
-
Time Complexity: O(n)
-
Space Complexity: O(n)
-
๐ Common and effective approach using a stack
๐ง Optimized Stack Using Map
public boolean isValid(String s) {
Map<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put('}', '{');
map.put(']', '[');
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (map.containsKey(c)) {
char top = stack.isEmpty() ? '#' : stack.pop();
if (top != map.get(c)) {
return false;
}
} else {
stack.push(c);
}
}
return stack.isEmpty();
}
- ๐ Cleaner and easier to maintain when dealing with many bracket types
- โ Brute Force (Remove Pairs Iteratively)
๐ข Approach 3: Brute Force by Replacing Pairs
public boolean isValid(String s) {
while (s.contains("()") || s.contains("{}") || s.contains("[]")) {
s = s.replace("()", "")
.replace("{}", "")
.replace("[]", "");
}
return s.isEmpty();
}
- Time Complexity: O(nยฒ)
- Space Complexity: O(n) -๐ Good for understanding, but inefficient
โ๏ธ Approach 4: Using Deque Instead of Stack
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>();
for (char c : s.toCharArray()) {
if (c == '(') stack.push(')');
else if (c == '{') stack.push('}');
else if (c == '[') stack.push(']');
else if (stack.isEmpty() || stack.pop() != c) return false;
}
return stack.isEmpty();
}
- โก Faster and more efficient than Stack class
- โ Recommended in production scenarios
๐งช Test Cases
public class ValidParenthesesTest {
public static void main(String[] args) {
System.out.println(isValid("()")); // true
System.out.println(isValid("()[]{}")); // true
System.out.println(isValid("(]")); // false
System.out.println(isValid("([)]")); // false
System.out.println(isValid("{[]}")); // true
}
public static boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '{' || c == '[') {
stack.push(c);
} else if (!stack.isEmpty() &&
((c == ')' && stack.peek() == '(') ||
(c == '}' && stack.peek() == '{') ||
(c == ']' && stack.peek() == '['))) {
stack.pop();
} else {
return false;
}
}
return stack.isEmpty();
}
}
๐ Notes
- Always push opening brackets and pop when matching closing ones arrive
- Avoid using Stack
for high-performance environments โ use Deque instead - Validate null or empty strings in real-world scenarios
- Always validate input string length.
- Avoid using legacy Stack in Java; prefer Deque for performance.
- These techniques are applicable to many bracket-matching problems (HTML tag parsing, compilers, etc.).
Related Posts
Java Interview Guide - Part 5: Advanced Java Concepts (Q41โQ50)
A comprehensive list of essential Java interview questions covering OOP, memory management, exceptions, collections, and Streams
Java Interview Guide - Part 0: Core Questions (1โ50)
A comprehensive list of essential Java interview questions covering OOP, memory management, exceptions, collections, Streams, JDBC
Complete Java Mastery
A complete guide to mastering Java, covering core concepts, collections, multithreading, JDBC, and more โ curated by the InDepthDev Backend Team to help you crack interviews and build real-world expertise.