Valid Parentheses is the #5 most asked LeetCode problem globally — and the canonical introduction to the Stack data structure in interviews.
Our analysis of 10,385 verified interview questions across 259 companies shows this problem appeared 119 times across 48 companies — including Google, Amazon, Meta, Microsoft, Bloomberg, Goldman Sachs, Mastercard, Millennium, LinkedIn, and Intuit.
It looks deceptively simple. But interviewers use it to test three things: whether you immediately reach for a stack, whether you handle all edge cases cleanly, and whether you can extend the solution to harder variants on the fly. This guide covers all three.
| Metric | Value |
|---|---|
| Total Interview Appearances | 119 verified mentions |
| Companies That Ask It | 48 companies |
| Global Rank | #5 out of 10,385 questions |
| Difficulty | Easy |
| Core Patterns | Stack, String |
Google, Amazon, Meta, Microsoft, Bloomberg, Goldman Sachs, Mastercard, Millennium, LinkedIn, Intuit, Adobe, Airbnb, Barclays, BlackRock, Capital One, Cisco, DE Shaw, Disney, Expedia, GE Healthcare, Grab, Huawei, IBM, Infosys, Intel, J.P. Morgan, Morgan Stanley, and 21 more.
Valid Parentheses is asked universally because it is the simplest possible problem that requires a stack. If you solve it with any other approach, you either make it too complex or miss edge cases. Interviewers use it to verify that you understand when and why to use a stack — a skill that transfers directly to harder problems like Largest Rectangle in Histogram, Daily Temperatures, and Decode String.
LeetCode #20 — Valid Parentheses
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Input: s = "()" Output: true
Input: s = "()[]{}" Output: true
Input: s = "(]" Output: false
Input: s = "([)]" Output: false // wrong order
Input: s = "{[]}" Output: true // correctly nested
Input: s = "(" Output: false // unclosed bracket
Input: s = "]" Output: false // no matching open
The key property of valid bracket sequences: the most recently opened bracket must be the first one closed. This is exactly the Last-In-First-Out (LIFO) property of a stack.
Think of it like nested boxes. When you open a box (push to stack), the next thing you close must be that same box (pop from stack and verify match). You can't close an outer box before closing the inner ones.
Push every opening bracket onto the stack. When you see a closing bracket, check if the top of the stack is its matching opener. If not — or if the stack is empty — return false. At the end, the stack must be empty.
closing → opening (e.g., ')' → '(').s:
(, [, {) → push to stack.false (nothing to match).false.true if stack is empty, false otherwise.Tracing s = "{[]}":
| Step | Char | Action | Stack |
|---|---|---|---|
| 1 | { | Opening → push | ['{'] |
| 2 | [ | Opening → push | ['{', '['] |
| 3 | ] | Closing → pop '[', matches ✅ | ['{'] |
| 4 | } | Closing → pop '{', matches ✅ | [] |
| End | — | Stack empty → return true | [] |
Tracing s = "([)]" — the tricky case:
| Step | Char | Action | Stack |
|---|---|---|---|
| 1 | ( | Opening → push | ['('] |
| 2 | [ | Opening → push | ['(', '['] |
| 3 | ) | Closing → pop '[', expected '(' ❌ | — |
| End | — | Mismatch → return false | — |
def isValid(s: str) -> bool:
stack = []
mapping = {')': '(', '}': '{', ']': '['}
for char in s:
if char in mapping:
# Closing bracket
top = stack.pop() if stack else '#'
if mapping[char] != top:
return False
else:
# Opening bracket
stack.append(char)
return not stack # True if all brackets matched
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>();
Map<Character, Character> mapping = new HashMap<>();
mapping.put(')', '(');
mapping.put('}', '{');
mapping.put(']', '[');
for (char c : s.toCharArray()) {
if (mapping.containsKey(c)) {
// Closing bracket
char top = stack.isEmpty() ? '#' : stack.pop();
if (mapping.get(c) != top) return false;
} else {
// Opening bracket
stack.push(c);
}
}
return stack.isEmpty();
}
}
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function(s) {
const stack = [];
const mapping = { ')': '(', '}': '{', ']': '[' };
for (const char of s) {
if (mapping[char]) {
// Closing bracket
const top = stack.length ? stack.pop() : '#';
if (mapping[char] !== top) return false;
} else {
// Opening bracket
stack.push(char);
}
}
return stack.length === 0;
};
"(((((") every character is pushed onto the stack before any match is found.Interview-ready explanation: "Time is O(n) — one pass, constant work per character. Space is O(n) in the worst case when the entire string is opening brackets and nothing has been matched yet."
| Input | Expected | Why It's Tricky |
|---|---|---|
"" | true | Empty string — stack stays empty, return true |
")" | false | Closing bracket on empty stack |
"((" | false | Stack not empty at end |
"([)]" | false | Correct count but wrong nesting order |
"{[]}" | true | Properly nested mixed brackets |
"]" | false | Single unmatched closing bracket |
Forgetting to check if the stack is empty before popping when you encounter a closing bracket. Always guard with: top = stack.pop() if stack else '#'. Calling pop on an empty stack throws an exception and will crash your solution.
Valid Parentheses is the entry point to a family of stack problems. Every variant uses the same core push/pop mechanic — just with more complex conditions.
"Remove the minimum number of brackets to make the string valid."
Insight: Use a stack to track indices of unmatched opening brackets. After scanning, all indices still in the stack (unmatched opens) plus positions of unmatched closes must be removed.
"Find the length of the longest valid parentheses substring."
Insight: Push indices onto the stack instead of characters. When a match is found, the current valid length is right_index - stack_top_index. Push -1 as a sentinel base.
def longestValidParentheses(s):
stack = [-1] # sentinel base index
max_len = 0
for i, char in enumerate(s):
if char == '(':
stack.append(i)
else:
stack.pop()
if not stack:
stack.append(i) # new base
else:
max_len = max(max_len, i - stack[-1])
return max_len
"For each day, find how many days until a warmer temperature."
Insight: Monotonic stack — push indices of unresolved days. When a warmer day arrives, pop and calculate the difference.
def dailyTemperatures(temperatures):
result = [0] * len(temperatures)
stack = [] # indices waiting for a warmer day
for i, temp in enumerate(temperatures):
while stack and temperatures[stack[-1]] < temp:
idx = stack.pop()
result[idx] = i - idx
stack.append(i)
return result
"Decode a string like '3[a2[c]]' → 'accaccacc'."
Insight: Two stacks — one for counts, one for strings. Push both when you see [. Pop and combine when you see ].
"Find the largest rectangle that fits in a histogram."
Insight: Monotonic increasing stack of bar indices. When a shorter bar is found, pop and calculate area using the current bar as the right boundary.
"Calculate the score where () = 1, AB = A+B, and (A) = 2A."
Insight: Push 0 as a base score on (. On ), pop and either add 1 (if inner was 0) or double the inner score, then add to the new top.
| Problem | Stack Stores | Key Operation |
|---|---|---|
| LC #20 Valid Parens | Opening brackets | Match on close |
| LC #1249 Min Remove | Unmatched indices | Remove leftover indices |
| LC #32 Longest Valid | Indices (sentinel) | Length = i - stack top |
| LC #739 Daily Temps | Unresolved indices | Pop when warmer found |
| LC #394 Decode String | Counts + strings | Pop and repeat on ] |
| LC #84 Histogram | Bar indices | Pop when shorter bar found |
Any recursive solution can be converted to an explicit stack. If a problem has naturally nested subproblems (decode string, evaluate expressions), both work — but an explicit stack avoids call stack overflow on large inputs and is generally preferred in interviews for clarity.
With 119 appearances across 48 companies including every major FAANG and finance firm, you cannot afford to blank on the stack approach for Valid Parentheses.
Tag all stack problems on DSAPrep.dev under Stack and Monotonic Stack. The spaced repetition system will resurface them at exactly the right intervals.
One problem at a time. One review at a time. Future you will thank present you.