LeetCode ยท #20

Valid Parentheses Solution

Given a string containing just (, ), {, }, [, ], determine if the input string is valid.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Easy

๐Ÿ”—

LeetCode

Problem #20

๐Ÿ—๏ธ

Pattern

Stack โ€” bracket matching

A string is valid if: (1) open brackets are closed by the same type of bracket, (2) open brackets are closed in the correct order, and (3) every close bracket has a corresponding open bracket of the same type.

Example 1
Input: s = "()[]" Output: true
Example 2
Input: s = "(]" Output: false
Example 3
Input: s = "([)]" Output: false // Interleaved โ€” wrong nesting order
Constraints
โ€ข 1 โ‰ค s.length โ‰ค 10โด โ€ข s consists of parentheses only: '()[]{}'
02
Section Two ยท Approach 1

Brute Force โ€” Repeated Replace

Repeatedly scan the string and remove adjacent matching pairs (), [], {}. If the string becomes empty, it's valid. Each pass removes at most n/2 pairs, so up to n/2 passes โ†’ O(nยฒ).

Problem: O(nยฒ) from repeated string scanning. A stack processes every character in a single O(n) pass โ€” push openers, pop and match closers.
Java โ€” Repeated Replace
class Solution { public boolean isValid(String s) { int prev = -1; while (s.length() != prev) { prev = s.length(); s = s.replace("()", "").replace("[]", "").replace("{}", ""); } return s.isEmpty(); } }
Python โ€” Repeated Replace
class Solution: def isValid(self, s: str) -> bool: while '()' in s or '[]' in s or '{}' in s: s = s.replace('()', '').replace('[]', '').replace('{}', '') return s == ''
MetricValue
TimeO(nยฒ)
SpaceO(n) โ€” string copies
03
Section Three ยท Approach 2

Stack โ€” O(n)

Scan left to right. When you see an opening bracket, push it onto the stack. When you see a closing bracket, pop the stack and check if the popped opener matches. If the stack is empty when you try to pop, or the bracket doesn't match, it's invalid. At the end, the stack must be empty.

๐Ÿ’ก Mental model: Think of stacking plates. Each opening bracket adds a plate. Each closing bracket takes a plate off โ€” but only if it's the right color. If you try to remove a plate that doesn't match, or there are no plates to remove, the stack is broken. At the end, a clean table (empty stack) means everything matched.
Algorithm
  • Step 1: Create an empty stack and a map: { ')':'(', ']':'[', '}':'{' }.
  • Step 2: For each character: if it's an opener, push it. If it's a closer, pop and check match.
  • Step 3: If stack is empty on pop or pop doesn't match โ†’ return false.
  • Step 4: After scanning, return stack.isEmpty().
๐ŸŽฏ When to recognize this pattern:
  • Any problem involving matching nested pairs โ€” parentheses, HTML tags, function calls โ€” think stack.
  • The LIFO property naturally handles nesting: the most recently opened thing must be closed first.
04
Section Four ยท Trace

Visual Walkthrough

Trace through s = "{[()]}":

Stack โ€” push openers, pop and match closers
INPUT STRING { [ ( ) ] } STACK (grows โ†‘) ( โ† top [ { โ† bottom after 3 pushes STEP-BY-STEP โ‘  '{' opener โ†’ push stack: [{] โ‘ก '[' opener โ†’ push stack: [{, [] โ‘ข '(' opener โ†’ push stack: [{, [, (] โ‘ฃ ')' closer โ†’ pop '(' โœ“ matches! stack: [{, [] โ‘ค ']' closer โ†’ pop '[' โœ“ matches! stack: [{] โ‘ฅ '}' closer โ†’ pop '{' โœ“ matches! stack: [] All characters processed. Stack is empty โ†’ valid! Answer: true โœ“
05
Section Five ยท Implementation

Code โ€” Java & Python

Java โ€” Stack
import java.util.Stack; import java.util.Map; class Solution { 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)) { // closer if (stack.isEmpty() || stack.pop() != map.get(c)) return false; } else { stack.push(c); // opener } } return stack.isEmpty(); } }
Python โ€” Stack
class Solution: def isValid(self, s: str) -> bool: stack = [] match = {')': '(', ']': '[', '}': '{'} for c in s: if c in match: if not stack or stack.pop() != match[c]: return False else: stack.append(c) return len(stack) == 0
06
Section Six ยท Analysis

Complexity Analysis

ApproachTimeSpaceTrade-off
Repeated ReplaceO(nยฒ)O(n)Simple but slow string rebuilds
Stack โ† optimal O(n) O(n) One pass. Stack holds at most n/2 openers.
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

CaseInputWhy It Matters
Odd length"("Odd-length strings are always invalid โ€” brackets come in pairs.
Single pair"()"Minimal valid input.
Closer first")"Stack empty on first pop โ†’ false.
Wrong nesting"([)]"Pop gives '[' but closer is ')' โ†’ mismatch.
Deep nesting"(((())))"Stack grows to n/2, then unwinds. Valid.
โš  Common Mistake: Forgetting to check stack.isEmpty() at the end. A string like "((" passes all pop checks (no closers to fail) but leaves unmatched openers on the stack. The final empty check catches this.

โ† Back to Stack problems