Bracket Up, Stack Down – Valid Parentheses

Valid Parentheses – Keeping Brackets in Check

Problem Statement

Given a string s 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.

  • Every close bracket has a corresponding open bracket.

Best Data Structure for the Job

Stack is the MVP here.

Why?

  • Perfect for Last In, First Out (LIFO) logic

  • Helps track nested and sequential brackets

  • Efficient and intuitive for validation problems like this on

Different Approaches

1)Brute Force with Replacements

Keep removing valid pairs like "()", "{}", and "[]" until nothing can be removed. If the string becomes empty, it was valid.


public boolean isValid(String s) { while (s.contains("()") || s.contains("[]") || s.contains("{}")) { s = s.replace("()", "").replace("[]", "").replace("{}", ""); } return s.isEmpty(); }

2)Stack-Based Validation 

Use a stack to push opening brackets. On encountering a closing bracket, pop from the stack and validate the pair.


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()) return false; char top = stack.pop(); if ((c == ')' && top != '(') || (c == '}' && top != '{') || (c == ']' && top != '[')) { return false; } } } return stack.isEmpty(); }

3)Stack + HashMap 

Use a map to store matching pairs and simplify conditionals. Push expected closing brackets into the stack instead of open ones.


public boolean isValid(String s) { Stack<Character> stack = new Stack<>(); Map<Character, Character> map = Map.of( ')', '(', '}', '{', ']', '[' ); for (char c : s.toCharArray()) { if (map.containsKey(c)) { if (stack.isEmpty() || stack.pop() != map.get(c)) return false; } else { stack.push(c); } } return stack.isEmpty(); }

4)Optimized Approach – Array Stack + Switch Case

This one’s a beast ;Fast, memory-efficient, and clean.

public boolean isValid(String s) { int index = -1; char[] stack = new char[s.length()]; for (char ch : s.toCharArray()) { switch (ch) { case '}': if (index == -1 || stack[index--] != '{') return false; break; case ']': if (index == -1 || stack[index--] != '[') return false; break; case ')': if (index == -1 || stack[index--] != '(') return false; break; default: stack[++index] = ch; } } return index == -1; }

  • No Java Stack class
  • Switch is super fast
  • You control the memory, and avoid object overhead

⚠️ Common Mistakes to Avoid

  • Not checking if the stack is empty before popping

  • Forgetting to validate leftover items in the stack

  • Misusing brackets (e.g., pushing the wrong pair)

  • Skipping edge case numRows = 1 or s.length = 1

📊 Time and Space Complexity

  • Brute Force:

    • Time: O(n²)

    • Space: O(n)

  • Stack / Stack + HashMap/ Array Stack+Switch:

    • Time: O(n)

    • Space: O(n)

🌍 Real-World Applications

  • Syntax checkers in compilers

  • Validating HTML/XML structure

  • Expression parsers in calculators

  • Editors that highlight unclosed brackets


I hope you found this article insightful! Keep exploring, keep learning, and don’t forget to check back daily for more exciting problem breakdowns. If you know someone who would benefit from this, share it with them and help them grow too! That’s it for today—see you in the next post!

                                                                                                                                         Signing off!! 

                                                                                                Master DSA One Problem at a Time :)

Comments

Popular posts from this blog

Trailing Zeros in Factorial – How Many and Why?

Divisible Drama — Who’s In, Who’s Out?

Zero Array After Queries