Valid Parentheses
Problem Statement
Section titled “Problem Statement”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 closing bracket.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
Examples
Section titled “Examples”| Input | Valid? | Explanation |
|---|---|---|
"()" | true | Simple pair of parentheses |
"()[]{}" | true | Three different pairs, all properly closed |
"(]" | false | Closing bracket does not match opening bracket |
"([{}])" | true | Nested brackets in correct order |
"([)]" | false | Brackets closed in wrong order (interleaved) |
"" | true | Empty string is valid |
"(" | false | Unclosed opening bracket |
")" | false | Closing bracket with no opening |
Constraints
Section titled “Constraints”0 <= s.length <= 10^4sconsists of parentheses only:'(', ')', '[', ']', '{', '}'
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Intuition | Best When |
|---|---|---|---|---|
| Stack | O(n) | O(n) | Process left-to-right, match using memory | General case — fast and clear |
| Replace Loop | O(n²) | O(n) | Remove pairs repeatedly | Learning the concept, simple implementation |
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick Stack if you want the best all-around solution.
- Pick Replace Loop if you want to understand the concept through a brute-force lens.
Approach 1: Stack (Recommended)
Section titled “Approach 1: Stack (Recommended)”Use a stack to track opening brackets. When you encounter a closing bracket, check if it matches the most recent opening bracket on the stack.
Key insight: The last opened bracket that hasn’t been closed yet must match the current closing bracket. This is exactly what a stack provides — last-in-first-out (LIFO) access.
Step-by-step Example
Section titled “Step-by-step Example”Input: s = "([{}])"
| Step | Char | Stack (before) | Action | Stack (after) |
|---|---|---|---|---|
| 1 | ( | [] | Opening bracket → push | ['('] |
| 2 | [ | ['('] | Opening bracket → push | ['(', '['] |
| 3 | { | ['(', '['] | Opening bracket → push | ['(', '[', '{'] |
| 4 | } | ['(', '[', '{'] | Closing bracket → top is { → match! pop | ['(', '['] |
| 5 | ] | ['(', '['] | Closing bracket → top is [ → match! pop | ['('] |
| 6 | ) | ['('] | Closing bracket → top is ( → match! pop | [] |
| End | — | [] | Stack empty → valid ✓ | — |
Input: s = "([)]"
| Step | Char | Stack (before) | Action | Result |
|---|---|---|---|---|
| 1 | ( | [] | Opening bracket → push | ['('] |
| 2 | [ | ['('] | Opening bracket → push | ['(', '['] |
| 3 | ) | ['(', '['] | Closing bracket → top is [, but we see ) → no match! ✗ | Invalid |
Animated walkthrough
Watch the stack grow and shrink as opening brackets are pushed and closing brackets are matched and popped.
Pseudocode
Section titled “Pseudocode”function validParenthesesStack(s): stack = [] bracketMap = {'(': ')', '[': ']', '{': '}'}
for char in s: if char is an opening bracket: stack.push(char) else: if stack is empty or bracketMap[stack.pop()] != char: return false
return stack is emptySolution Code
Section titled “Solution Code”from typing import List
def valid_parentheses_stack(s: str) -> bool: """ Check if parentheses are balanced using a stack.
Approach: Use a stack to match closing brackets with opening brackets. - Push opening brackets onto the stack - For each closing bracket, check if it matches the top of the stack - At the end, the stack should be empty
Time: O(n) - single pass through the string Space: O(n) - stack size in worst case (all opening brackets) """ stack = [] bracket_map = {'(': ')', '[': ']', '{': '}'}
for char in s: if char in bracket_map: # Opening bracket - push to stack stack.append(char) else: # Closing bracket - check if it matches if not stack or bracket_map[stack.pop()] != char: return False
# Stack should be empty (all brackets matched) return len(stack) == 0
if __name__ == "__main__": # Test cases print(valid_parentheses_stack("()")) # True print(valid_parentheses_stack("()[]{}")) # True print(valid_parentheses_stack("(]")) # False print(valid_parentheses_stack("([])")) # True print(valid_parentheses_stack("{[]}")) # True print(valid_parentheses_stack("")) # True print(valid_parentheses_stack("(")) # False print(valid_parentheses_stack(")")) # False#include <iostream>#include <stack>#include <string>#include <unordered_map>
bool validParenthesesStack(std::string s) { /** * Check if parentheses are balanced using a stack. * * Approach: Use a stack to match closing brackets with opening brackets. * - Push opening brackets onto the stack * - For each closing bracket, check if it matches the top of the stack * - At the end, the stack should be empty * * Time: O(n) - single pass through the string * Space: O(n) - stack size in worst case (all opening brackets) */ std::stack<char> st; std::unordered_map<char, char> bracket_map = { {'(', ')'}, {'[', ']'}, {'{', '}'} };
for (char c : s) { if (bracket_map.count(c)) { // Opening bracket - push to stack st.push(c); } else { // Closing bracket - check if it matches if (st.empty() || bracket_map[st.top()] != c) { return false; } st.pop(); } }
// Stack should be empty (all brackets matched) return st.empty();}
int main() { // Test cases std::cout << validParenthesesStack("()") << std::endl; // 1 std::cout << validParenthesesStack("()[]{}") << std::endl; // 1 std::cout << validParenthesesStack("(]") << std::endl; // 0 std::cout << validParenthesesStack("([])") << std::endl; // 1 std::cout << validParenthesesStack("{[]}") << std::endl; // 1 std::cout << validParenthesesStack("") << std::endl; // 1 std::cout << validParenthesesStack("(") << std::endl; // 0 std::cout << validParenthesesStack(")") << std::endl; // 0 return 0;}import java.util.Stack;import java.util.HashMap;
public class Main { /** * Check if parentheses are balanced using a stack. * * Approach: Use a stack to match closing brackets with opening brackets. * - Push opening brackets onto the stack * - For each closing bracket, check if it matches the top of the stack * - At the end, the stack should be empty * * Time: O(n) - single pass through the string * Space: O(n) - stack size in worst case (all opening brackets) */ public static boolean validParenthesesStack(String s) { Stack<Character> stack = new Stack<>(); HashMap<Character, Character> bracketMap = new HashMap<>(); bracketMap.put('(', ')'); bracketMap.put('[', ']'); bracketMap.put('{', '}');
for (char c : s.toCharArray()) { if (bracketMap.containsKey(c)) { // Opening bracket - push to stack stack.push(c); } else { // Closing bracket - check if it matches if (stack.isEmpty() || bracketMap.get(stack.pop()) != c) { return false; } } }
// Stack should be empty (all brackets matched) return stack.isEmpty(); }
public static void main(String[] args) { // Test cases System.out.println(validParenthesesStack("()")); // true System.out.println(validParenthesesStack("()[]{}")); // true System.out.println(validParenthesesStack("(]")); // false System.out.println(validParenthesesStack("([])")); // true System.out.println(validParenthesesStack("{[]}")); // true System.out.println(validParenthesesStack("")); // true System.out.println(validParenthesesStack("(")); // false System.out.println(validParenthesesStack(")")); // false }}/** * Check if parentheses are balanced using a stack. * * Approach: Use a stack to match closing brackets with opening brackets. * - Push opening brackets onto the stack * - For each closing bracket, check if it matches the top of the stack * - At the end, the stack should be empty * * Time: O(n) - single pass through the string * Space: O(n) - stack size in worst case (all opening brackets) */function validParenthesesStack(s) { const stack = []; const bracketMap = { '(': ')', '[': ']', '{': '}' };
for (const char of s) { if (char in bracketMap) { // Opening bracket - push to stack stack.push(char); } else { // Closing bracket - check if it matches if (stack.length === 0 || bracketMap[stack.pop()] !== char) { return false; } } }
// Stack should be empty (all brackets matched) return stack.length === 0;}
// Test casesconsole.log(validParenthesesStack("()")); // trueconsole.log(validParenthesesStack("()[]{}")); // trueconsole.log(validParenthesesStack("(]")); // falseconsole.log(validParenthesesStack("([])")); // trueconsole.log(validParenthesesStack("{[]}")); // trueconsole.log(validParenthesesStack("")); // trueconsole.log(validParenthesesStack("(")); // falseconsole.log(validParenthesesStack(")")); // falseuse std::collections::HashMap;
/** * Check if parentheses are balanced using a stack. * * Approach: Use a stack to match closing brackets with opening brackets. * - Push opening brackets onto the stack * - For each closing bracket, check if it matches the top of the stack * - At the end, the stack should be empty * * Time: O(n) - single pass through the string * Space: O(n) - stack size in worst case (all opening brackets) */fn valid_parentheses_stack(s: &str) -> bool { let mut stack = Vec::new(); let mut bracket_map = HashMap::new(); bracket_map.insert('(', ')'); bracket_map.insert('[', ']'); bracket_map.insert('{', '}');
for c in s.chars() { if bracket_map.contains_key(&c) { // Opening bracket - push to stack stack.push(c); } else { // Closing bracket - check if it matches if let Some(last) = stack.pop() { if bracket_map.get(&last) != Some(&c) { return false; } } else { return false; } } }
// Stack should be empty (all brackets matched) stack.is_empty()}
fn main() { // Test cases println!("{}", valid_parentheses_stack("()")); // true println!("{}", valid_parentheses_stack("()[]{}")); // true println!("{}", valid_parentheses_stack("(]")); // false println!("{}", valid_parentheses_stack("([])")); // true println!("{}", valid_parentheses_stack("{[]}")); // true println!("{}", valid_parentheses_stack("")); // true println!("{}", valid_parentheses_stack("(")); // false println!("{}", valid_parentheses_stack(")")); // false}package main
import "fmt"
/** * Check if parentheses are balanced using a stack. * * Approach: Use a stack to match closing brackets with opening brackets. * - Push opening brackets onto the stack * - For each closing bracket, check if it matches the top of the stack * - At the end, the stack should be empty * * Time: O(n) - single pass through the string * Space: O(n) - stack size in worst case (all opening brackets) */func validParenthesesStack(s string) bool { stack := make([]rune, 0) bracketMap := map[rune]rune{ '(': ')', '[': ']', '{': '}', }
for _, c := range s { if val, ok := bracketMap[c]; ok { // Opening bracket - push to stack stack = append(stack, c) } else { // Closing bracket - check if it matches if len(stack) == 0 || bracketMap[stack[len(stack)-1]] != c { return false } stack = stack[:len(stack)-1] } }
// Stack should be empty (all brackets matched) return len(stack) == 0}
func main() { // Test cases fmt.Println(validParenthesesStack("()")) // true fmt.Println(validParenthesesStack("()[]{}")) // true fmt.Println(validParenthesesStack("(]")) // false fmt.Println(validParenthesesStack("([])")) // true fmt.Println(validParenthesesStack("{[]}")) // true fmt.Println(validParenthesesStack("")) // true fmt.Println(validParenthesesStack("(")) // false fmt.Println(validParenthesesStack(")")) // false}Approach 2: Replace Loop
Section titled “Approach 2: Replace Loop”Repeatedly remove consecutive pairs of matching brackets until no more can be removed. If the string becomes empty, it is valid.
This approach is conceptually simpler but less efficient. It directly models the idea that valid brackets always have matching pairs next to each other.
Step-by-step Example
Section titled “Step-by-step Example”Input: s = "([{}])"
| Pass | Current String | Pairs Removed | Next String |
|---|---|---|---|
| 1 | "([{}])" | {} | "([])" |
| 2 | "([])" | [] | "()" |
| 3 | "()" | () | "" |
| End | "" | — | Valid ✓ |
Input: s = "([)]"
| Pass | Current String | Pairs Removed | Next String |
|---|---|---|---|
| 1 | "([)]" | — | "([)]" |
| End | "([)]" | No pairs to remove | Invalid ✗ |
Pseudocode
Section titled “Pseudocode”function validParenthesesReplace(s): while s contains "()" or "[]" or "{}": remove all occurrences of "()", "[]", "{}" return s is emptySolution Code
Section titled “Solution Code”def valid_parentheses_replace(s: str) -> bool: """ Check if parentheses are balanced by repeatedly removing matched pairs.
Approach: Repeatedly remove consecutive pairs of matching brackets until either the string is empty (valid) or no more pairs can be removed (invalid).
Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes Space: O(n) - for temporary string during replacement
Note: This approach is simple to understand but slower than stack. """ while "()" in s or "[]" in s or "{}" in s: s = s.replace("()", "").replace("[]", "").replace("{}", "")
return len(s) == 0
if __name__ == "__main__": # Test cases print(valid_parentheses_replace("()")) # True print(valid_parentheses_replace("()[]{}")) # True print(valid_parentheses_replace("(]")) # False print(valid_parentheses_replace("([])")) # True print(valid_parentheses_replace("{[]}")) # True print(valid_parentheses_replace("")) # True print(valid_parentheses_replace("(")) # False print(valid_parentheses_replace(")")) # False#include <iostream>#include <string>
bool validParenthesesReplace(std::string s) { /** * Check if parentheses are balanced by repeatedly removing matched pairs. * * Approach: Repeatedly remove consecutive pairs of matching brackets * until either the string is empty (valid) or no more pairs can be removed (invalid). * * Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes * Space: O(n) - for temporary strings during replacement * * Note: This approach is simple to understand but slower than stack. */ bool changed = true; while (changed) { changed = false; size_t pos = 0;
// Find and remove pairs while ((pos = s.find("()")) != std::string::npos) { s.erase(pos, 2); changed = true; } pos = 0; while ((pos = s.find("[]")) != std::string::npos) { s.erase(pos, 2); changed = true; } pos = 0; while ((pos = s.find("{}")) != std::string::npos) { s.erase(pos, 2); changed = true; } }
return s.empty();}
int main() { // Test cases std::cout << validParenthesesReplace("()") << std::endl; // 1 std::cout << validParenthesesReplace("()[]{}") << std::endl; // 1 std::cout << validParenthesesReplace("(]") << std::endl; // 0 std::cout << validParenthesesReplace("([])") << std::endl; // 1 std::cout << validParenthesesReplace("{[]}") << std::endl; // 1 std::cout << validParenthesesReplace("") << std::endl; // 1 std::cout << validParenthesesReplace("(") << std::endl; // 0 std::cout << validParenthesesReplace(")") << std::endl; // 0 return 0;}public class Main { /** * Check if parentheses are balanced by repeatedly removing matched pairs. * * Approach: Repeatedly remove consecutive pairs of matching brackets * until either the string is empty (valid) or no more pairs can be removed (invalid). * * Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes * Space: O(n) - for temporary strings during replacement * * Note: This approach is simple to understand but slower than stack. */ public static boolean validParenthesesReplace(String s) { String prev; do { prev = s; s = s.replace("()", "").replace("[]", "").replace("{}", ""); } while (!s.equals(prev));
return s.length() == 0; }
public static void main(String[] args) { // Test cases System.out.println(validParenthesesReplace("()")); // true System.out.println(validParenthesesReplace("()[]{}")); // true System.out.println(validParenthesesReplace("(]")); // false System.out.println(validParenthesesReplace("([])")); // true System.out.println(validParenthesesReplace("{[]}")); // true System.out.println(validParenthesesReplace("")); // true System.out.println(validParenthesesReplace("(")); // false System.out.println(validParenthesesReplace(")")); // false }}/** * Check if parentheses are balanced by repeatedly removing matched pairs. * * Approach: Repeatedly remove consecutive pairs of matching brackets * until either the string is empty (valid) or no more pairs can be removed (invalid). * * Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes * Space: O(n) - for temporary strings during replacement * * Note: This approach is simple to understand but slower than stack. */function validParenthesesReplace(s) { let prev; do { prev = s; s = s.replace(/\(\)/g, "").replace(/\[\]/g, "").replace(/\{\}/g, ""); } while (s !== prev);
return s.length === 0;}
// Test casesconsole.log(validParenthesesReplace("()")); // trueconsole.log(validParenthesesReplace("()[]{}")); // trueconsole.log(validParenthesesReplace("(]")); // falseconsole.log(validParenthesesReplace("([])")); // trueconsole.log(validParenthesesReplace("{[]}")); // trueconsole.log(validParenthesesReplace("")); // trueconsole.log(validParenthesesReplace("(")); // falseconsole.log(validParenthesesReplace(")")); // false/** * Check if parentheses are balanced by repeatedly removing matched pairs. * * Approach: Repeatedly remove consecutive pairs of matching brackets * until either the string is empty (valid) or no more pairs can be removed (invalid). * * Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes * Space: O(n) - for temporary strings during replacement * * Note: This approach is simple to understand but slower than stack. */fn valid_parentheses_replace(mut s: String) -> bool { let mut prev; loop { prev = s.clone(); s = s.replace("()", "").replace("[]", "").replace("{}", ""); if s == prev { break; } }
s.is_empty()}
fn main() { // Test cases println!("{}", valid_parentheses_replace("()".to_string())); // true println!("{}", valid_parentheses_replace("()[]{}".to_string())); // true println!("{}", valid_parentheses_replace("(]".to_string())); // false println!("{}", valid_parentheses_replace("([])".to_string())); // true println!("{}", valid_parentheses_replace("{[]}".to_string())); // true println!("{}", valid_parentheses_replace("".to_string())); // true println!("{}", valid_parentheses_replace("(".to_string())); // false println!("{}", valid_parentheses_replace(")".to_string())); // false}package main
import ( "fmt" "strings")
/** * Check if parentheses are balanced by repeatedly removing matched pairs. * * Approach: Repeatedly remove consecutive pairs of matching brackets * until either the string is empty (valid) or no more pairs can be removed (invalid). * * Time: O(n²) - each pass removes at least 2 characters, up to n/2 passes * Space: O(n) - for temporary strings during replacement * * Note: This approach is simple to understand but slower than stack. */func validParenthesesReplace(s string) bool { prev := "" for s != prev { prev = s s = strings.ReplaceAll(s, "()", "") s = strings.ReplaceAll(s, "[]", "") s = strings.ReplaceAll(s, "{}", "") }
return len(s) == 0}
func main() { // Test cases fmt.Println(validParenthesesReplace("()")) // true fmt.Println(validParenthesesReplace("()[]{}")) // true fmt.Println(validParenthesesReplace("(]")) // false fmt.Println(validParenthesesReplace("([])")) // true fmt.Println(validParenthesesReplace("{[]}")) // true fmt.Println(validParenthesesReplace("")) // true fmt.Println(validParenthesesReplace("(")) // false fmt.Println(validParenthesesReplace(")")) // false}Common mistakes
Section titled “Common mistakes”Approach 3: Space-Optimized Variant
Section titled “Approach 3: Space-Optimized Variant”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Valid Parentheses"""
def solve(): """Implementation for approach 3 of Valid Parentheses""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Valid Parentheses// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Valid Parentheses * Approach 3 */public class ValidParenthesesSpaceOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Valid Parentheses * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Valid Parentheses/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Valid Parentheses// Approach 3
func main() {{ fmt.Println("Solution implementation")}}