Loading problems...
TL;DR: Use a LIFO (Last-In-First-Out) stack to track open brackets, ensuring that every closing bracket matches the most recently seen open bracket of the same type.
The LeetCode 20 problem, "Valid Parentheses," asks us to validate the structure of a string containing only parentheses, brackets, and braces. A string is considered valid if open brackets are closed by the same type of brackets in the correct order. This is a fundamental problem in parsing and syntax analysis, often serving as the "Hello World" for stack-based algorithms.
A naive approach attempts to solve the problem by repeatedly finding and removing valid adjacent pairs. Since a valid string like ([]) must contain at least one innermost pair (like []), we can iteratively remove them until the string is empty or no pairs remain.
Pseudo-code:
textreplace "()" with empty string replace "[]" with empty string replace "{}" with empty string if string is empty return true else return false
Complexity Analysis:
((((...))))), we iterate through the string roughly times, and the string replacement operation takes time.Why it fails: While correct logically, this approach is inefficient. Modifying strings repeatedly is costly. With constraints up to characters, an solution performs roughly operations, which risks a Time Limit Exceeded (TLE) or performs very poorly compared to the optimal linear solution.
The key intuition for the LeetCode 20 solution lies in the nature of nested structures. When we encounter an open bracket, we cannot validate it immediately; we must wait for its corresponding closing bracket. However, we know that the first closing bracket we encounter must match the last open bracket we saw.
If we encounter a closing bracket }, it is valid if and only if the most recent pending open bracket is {. If the most recent open bracket is ( or [, the nesting is invalid (e.g., (}).
Technical Visualization: Imagine the algorithm as a cursor moving left to right.
At the end of the string, a valid input results in an empty stack, meaning all expectations were fulfilled.

Let's trace the algorithm with the input s = "([{}])".
[].(: It is an open bracket. Push to stack.
['('][: It is an open bracket. Push to stack.
['(', '[']{: It is an open bracket. Push to stack.
['(', '[', '{']}: It is a closing bracket.
{.} match {? Yes.['(', '[']]: It is a closing bracket.
[.] match [? Yes.['(']): It is a closing bracket.
(.) match (? Yes.[] (Empty)true.The algorithm is correct based on the invariant of the stack:
true only when the stack is empty ensures a 1:1 mapping.cpp#include <stack> #include <string> #include <unordered_map> class Solution { public: bool isValid(std::string s) { std::stack<char> st; for (char c : s) { // If it's an open bracket, push to stack if (c == '(' || c == '{' || c == '[') { st.push(c); } else { // If stack is empty, we have a closing bracket without an opener if (st.empty()) return false; char top = st.top(); // Check for mismatch if ((c == ')' && top != '(') || (c == '}' && top != '{') || (c == ']' && top != '[')) { return false; } // Valid match found, pop the open bracket st.pop(); } } // Stack must be empty for valid string return st.empty(); } };
javaimport java.util.Stack; class Solution { public boolean isValid(String s) { Stack<Character> stack = new Stack<>(); for (char c : s) { // If open bracket, push onto stack if (c == '(' || c == '{' || c == '[') { stack.push(c); } else { // If stack is empty, unbalanced closing bracket if (stack.isEmpty()) { return false; } char top = stack.pop(); // Check for matching pair if (c == ')' && top != '(') return false; if (c == '}' && top != '{') return false; if (c == ']' && top != '[') return false; } } // If stack is not empty, we have unmatched open brackets return stack.isEmpty(); } }
pythonclass Solution: def isValid(self, s: str) -> bool: stack = [] # Map closing brackets to their corresponding open brackets mapping = {")": "(", "}": "{", "]": "["} for char in s: if char in mapping: # It is a closing bracket # Pop the top element if stack is not empty, else assign dummy value top_element = stack.pop() if stack else '#' # If the mapped open bracket doesn't match the popped element, return False if mapping[char] != top_element: return False else: # It is an open bracket stack.append(char) # If the stack is empty, return True return not stack
(((((), the stack will contain all characters in the string.The Stack - Valid Parentheses Matching pattern is versatile. Understanding how to match elements using a stack helps solve several harder problems:
Why does the naive solution fail?
count++ for open, count-- for closed).([)] would pass a counter check but is invalid.Why do I get a Runtime Error (Empty Stack)?
stack.pop() or stack.peek() without checking stack.isEmpty() first.]Why does my code return true for (()?
true unconditionally after the loop finishes.stack.isEmpty().