You are given a string s consisting of the following characters: '(', ')', '{', '}', '[' and ']'.
The input string s is valid if and only if:
Return true if s is a valid string, and false otherwise.
Example 1:
Input: s = "[]"
Output: trueExample 2:
Input: s = "([{}])"
Output: trueExample 3:
Input: s = "[(])"
Output: falseExplanation: The brackets are not closed in the correct order.
Constraints:
1 <= s.length <= 1000
You should aim for a solution with O(n) time and O(n) space, where n is the length of the given string.
A brute force solution would be to continuously remove valid brackets until no more can be removed. If the remaining string is empty, return true; otherwise, return false. This would result in an O(n^2) solution. Can we think of a better approach? Perhaps a data structure could help.
We can use a stack to store characters. Iterate through the string by index. For an opening bracket, push it onto the stack. If the bracket is a closing type, check for the corresponding opening bracket at the top of the stack. If we don't find the corresponding opening bracket, immediately return false. Why does this work?
In a valid parenthesis expression, every opening bracket must have a corresponding closing bracket. The stack is used to process the valid string, and it should be empty after the entire process. This ensures that there is a valid substring between each opening and closing bracket.
Before attempting this problem, you should be comfortable with:
The idea is simple:
valid parentheses must always appear in matching pairs like "()", "{}", or "[]".
So if the string is valid, we can repeatedly remove these matching pairs until nothing is left.
If, after removing all possible pairs, the string becomes empty, then the parentheses were properly matched.
Otherwise, some unmatched characters remain, meaning the string is invalid.
"()", "{}", or "[]":true.false.Input: s = "({[]})"
We repeatedly remove matching pairs (), {}, [] until no more can be removed.
Initial String:
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5
Iteration 1:
Remove "()" → not found at adjacent positions
Remove "{}" → not found at adjacent positions
Remove "[]" → found at positions 2-3!
Found pair
↓↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
After removal:
┌───┬───┬───┬───┐
│ ( │ { │ } │ ) │
└───┴───┴───┴───┘
0 1 2 3
Iteration 2:
Remove "()" → not found at adjacent positions
Remove "{}" → found at positions 1-2!
Found pair
↓↓
┌───┬───┬───┬───┐
│ ( │ { │ } │ ) │
└───┴───┴───┴───┘
After removal:
┌───┬───┐
│ ( │ ) │
└───┴───┘
0 1
Iteration 3:
Remove "()" → found at positions 0-1!
Found pair
↓↓
┌───┬───┐
│ ( │ ) │
└───┴───┘
After removal:
┌───┐
│ │ ← Empty string!
└───┘
Final Result:
String is empty → return TrueValid parentheses must follow a last-opened, first-closed order — just like stacking plates.
So we use a stack to track opening brackets.
Whenever we see a closing bracket, we simply check whether it matches the most recent opening bracket on top of the stack.
If it matches, we remove that opening bracket.
If it doesn't match (or the stack is empty), the string is invalid.
A valid string ends with an empty stack.
stack to store opening brackets.c in the string:stack.stack is not empty and its top matches the corresponding opening bracket.stack.false.stack is empty, return true.false.Input: s = "({[]})"
We use a stack to track opening brackets and match them with closing brackets.
String (processing left to right):
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
0 1 2 3 4 5
Step 1: char = '('
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: '(' is an opening bracket → Push to stack
Stack:
┌───┐
│ ( │ ← top
└───┘
Step 2: char = '{'
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: '{' is an opening bracket → Push to stack
Stack:
┌───┐
│ { │ ← top
├───┤
│ ( │
└───┘
Step 3: char = '['
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: '[' is an opening bracket → Push to stack
Stack:
┌───┐
│ [ │ ← top
├───┤
│ { │
├───┤
│ ( │
└───┘
Step 4: char = ']'
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: ']' is a closing bracket
Top of stack is '[' which matches! → Pop from stack
Stack:
┌───┐
│ { │ ← top
├───┤
│ ( │
└───┘
Step 5: char = '}'
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: '}' is a closing bracket
Top of stack is '{' which matches! → Pop from stack
Stack:
┌───┐
│ ( │ ← top
└───┘
Step 6: char = ')'
Current char
↓
┌───┬───┬───┬───┬───┬───┐
│ ( │ { │ [ │ ] │ } │ ) │
└───┴───┴───┴───┴───┴───┘
Action: ')' is a closing bracket
Top of stack is '(' which matches! → Pop from stack
Stack:
┌───┐
│ │ ← empty
└───┘
Final Result:
Stack is empty → All brackets matched correctly!
Return: Trueclass Solution:
def isValid(self, s: str) -> bool:
stack = []
closeToOpen = { ")" : "(", "]" : "[", "}" : "{" }
for c in s:
if c in closeToOpen:
if stack and stack[-1] == closeToOpen[c]:
stack.pop()
else:
return False
else:
stack.append(c)
return True if not stack else FalseWhen encountering a closing bracket, you must verify the stack is not empty before checking the top element. Attempting to pop from an empty stack causes an error.
# Wrong: crashes on empty stack
if stack[-1] == closeToOpen[c]:
# Correct: check stack first
if stack and stack[-1] == closeToOpen[c]:After processing all characters, some opening brackets might remain unmatched. The string "(()" processes without errors but leaves "(" on the stack, making it invalid.
When building the bracket mapping, ensure closing brackets map to their corresponding opening brackets, not the other way around. The lookup should happen when you encounter a closing bracket.
# Correct mapping: closing -> opening
closeToOpen = {")": "(", "]": "[", "}": "{"}Using a queue instead of a stack fails because parentheses follow LIFO (last-in, first-out) order. The most recent opening bracket must be closed first, which requires stack behavior.