Valid Parentheses
Valid Parentheses: Mastering the Stack Data Structure
Welcome back to codinginterview.net. If "Two Sum" was your introduction to Hash Maps, "Valid Parentheses" is your ultimate initiation into the Stack data structure. By the end of this guide, you will understand exactly how to track nested structures and tackle this classic interview question with total confidence.
1. Understanding the Problem
You are given a string containing just the characters '(', ')', '{', '}', '[' and ']'. Your task is to determine if the input string is valid.
The Rules of Validity:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.
Quick Examples
"()"— Valid. Opens and closes perfectly."()[]{}"— Valid. They all close in the right order."(]"— Invalid. Mismatched bracket types."([)]"— Invalid. The order is wrong; you cannot close the parenthesis)before closing the square bracket]inside it.
2. The Core Intuition: Think Like a Stack
Imagine you are packing boxes inside of other boxes. Before you can tape up an outer box, you must finish packing and taping up the inner box. This "Last-In, First-Out" (LIFO) behavior is exactly how a Stack works.
Whenever you encounter a new opening bracket, you push it onto the top of your stack. Whenever you encounter a closing bracket, it must match whatever bracket is currently at the very top of your stack. If it doesn't match, or if the stack is empty when you try to close a bracket, the string is invalid.
3. The Logic Step-by-Step
To make the code clean, we can use a Hash Map (Dictionary) to pair our closing brackets with their corresponding opening brackets. Here is the algorithm:
- Initialize an empty Stack.
- Create a mapping of closing brackets to opening brackets (e.g.,
')' : '('). - Loop through each character in the string:
- If it is an opening bracket: Push it onto the Stack.
- If it is a closing bracket: Check the Stack. Is it empty? Does the top of the Stack match the required opening bracket? If no, return False. If yes, pop the top bracket off the Stack.
- At the very end, if the Stack is completely empty, return True (all brackets were matched and closed). If there are still brackets left, return False.
4. Complexity Analysis
- Time Complexity: O(N) — We iterate through the string of length N exactly one time. Pushing and popping from a stack takes O(1) time.
- Space Complexity: O(N) — In the worst-case scenario (e.g., all opening brackets like
"((((("), we will push every single character onto the Stack.
5. Code Implementations
Expand the sections below to see the optimal O(N) implementation in your preferred programming language.
View Python Solution
def isValid(s: str) -> bool:
stack = []
# Map closing brackets to their matching open brackets
bracket_map = {')': '(', '}': '{', ']': '['}
for char in s:
# If it's a closing bracket
if char in bracket_map:
# Pop from stack if it's not empty, otherwise assign a dummy value
top_element = stack.pop() if stack else '#'
# If the popped element doesn't match the mapped open bracket, it's invalid
if bracket_map[char] != top_element:
return False
else:
# It's an opening bracket, push to stack
stack.append(char)
# If the stack is empty, all brackets were matched properly
return not stack
View Java Solution
import java.util.Stack;
import java.util.HashMap;
class Solution {
public boolean isValid(String s) {
HashMap<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put('}', '{');
map.put(']', '[');
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// If the current character is a closing bracket
if (map.containsKey(c)) {
// Get the top element of the stack, or a dummy if empty
char topElement = stack.empty() ? '#' : stack.pop();
// If it doesn't match the corresponding opening bracket, return false
if (topElement != map.get(c)) {
return false;
}
} else {
// It's an opening bracket, push it onto the stack
stack.push(c);
}
}
// If stack is empty, it's valid
return stack.isEmpty();
}
}
View C++ Solution
#include <string>
#include <stack>
#include <unordered_map>
class Solution {
public:
bool isValid(std::string s) {
std::stack<char> st;
std::unordered_map<char, char> map = {
{')', '('},
{'}', '{'},
{']', '['}
};
for (char c : s) {
// If the character is a closing bracket
if (map.count(c)) {
char topElement = st.empty() ? '#' : st.top();
if (!st.empty()) {
st.pop();
}
if (topElement != map[c]) {
return false;
}
} else {
// It's an opening bracket
st.push(c);
}
}
return st.empty();
}
};
6. Conclusion: You Are Ready
You have successfully unlocked the Stack data structure. The "Valid Parentheses" problem teaches you how to maintain a history of unmatched elements and resolve them in reverse order. Whenever an interview question involves nesting, matching pairs, or needing to "go back" to the most recent item, your brain should immediately think: "I need a Stack." Keep practicing, and you'll spot these patterns instantly!