Valid Parentheses Problem
Algorithm · Starter
Step through it: Monotonic Stack pattern
Step 1 of 7
Goal: for each number, find the next bigger number to its right. Comparing every number with everything after it is slow. Instead keep a stack of numbers that are still waiting for a bigger one.
Step 2 of 7
Take 2. Nothing to compare yet, so it waits on the stack.
Step 3 of 7
Take 1. It is smaller than the waiting 2, so it cannot be anyone's answer. It waits too, on top.
Step 4 of 7
Take 5. It is bigger than 1, so 5 is the answer for 1. Pop 1. It is bigger than 2 as well, so pop 2 too. Then 5 waits.
Step 5 of 7
Take 3. Smaller than 5, so it waits on top.
Step 6 of 7
Take 6. It beats 3 and 5, so both get answer 6. Whatever is left never found a bigger number. Each number is pushed once and popped once, so it is one pass. The stack stays in decreasing order, which is why this is called a monotonic stack.
Step 7 of 7
Your turn.
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
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.
Example 1:
Input: s = "()"
Output: true
Example 2:
Input: s = "()[]{}"
Output: true
Example 3:
Input: s = "(]"
Output: false
This is actually a very common interview question and a very good example of how to use a stack data structure to solve problems.
Solution
The problem can be solved in two ways
Bruteforce Approach
We can iterate through the string and then for each character in the string, we check for it's last closing character in the the string. Once we find the last closing character in the string, we remove both characters and then repeat the iteration, if we don't find a closing character for an opening character, then the string is invalid. The time complexity of this would be O(n^2) which is not so efficient.
Using a Stack
We can use a hashtable to store all opening characters and the value would be the respective closing character. We can then iterate through the string and if we encounter an opening parantheses, we push it's closing character to the stack. If we ecounter a closing paraentheses, then we pop the stack and confirm that the popped element is equal to the current closing parentheses character. If it is not then the string is invalid. At the end of the iteration, we also need to check that the stack is empty. If it is not then the string is invalid. If it is, then the string is valid. This is a more efficient approach with a Time complexity and Space complexity of O(n).
Code
import Stack from '../../../data-structures/stack/Stack';
import HashTable from '../../../data-structures/hash-table/HashTable';
// Declare hashtable containg opening parentheses as key and it's closing parentheses as value.
const hashTable = new HashTable(3);
hashTable.set('{', '}');
hashTable.set('(', ')');
hashTable.set('[', ']');
/**
* Check if string has valid parentheses.
*
* @param {string} parenthesesString
* @return {boolean}
*/
export default function isValid(parenthesesString) {
// If string is empty return false
if (parenthesesString.length === 0) {
return false;
}
// Create stack
const stack = new Stack();
// Loop through each character of string
for (let i = 0; i < parenthesesString.length; i += 1) {
const currentCharacter = parenthesesString[i];
// If character is opening parentheses push it's closing parentheses to stack
if (hashTable.has(currentCharacter)) {
stack.push(hashTable.get(currentCharacter));
} else {
/* If character is a closing parentheses then,:
check If stack is empty, if it is return false.
if stack is not empty, pop from stack and compare it with current character.
If they are not same return false. */
if (stack.isEmpty() || stack.pop() !== currentCharacter) {
return false;
}
}
}
// If stack is empty return true else return false
return stack.isEmpty();
}References
Practice
Monotonic Stack
- Valid ParenthesesEasy
- Next Greater Element IEasy
- Min StackEasy
- Baseball GameEasy
- Remove All Adjacent Duplicates In StringEasy
- Daily TemperaturesMedium
- Next Greater Element IIMedium
- Evaluate Reverse Polish NotationMedium
- Decode StringMedium
- Remove K DigitsMedium
- Online Stock SpanMedium
- Car FleetMedium
- Asteroid CollisionMedium
- Simplify PathMedium
- 132 PatternMedium
- Sum of Subarray MinimumsMedium
- Largest Rectangle in HistogramHard
- Maximal RectangleHard
- Trapping Rain WaterHard
- Basic CalculatorHard
Spotted a mistake or something unclear? Report it on GitHub.