Valid Parenthesis
Question link: https://leetcode.com/problems/valid-parentheses/
Problem: Valid Parenthesis
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
Example 4:
Input: s = "([])"
Output: true
Constraints:
1 <= s.length <= 10^4
s
consists of parentheses only'()[]{}'
.
Walkthrough
Reading the question, we can see that what they want us to do is to check if the latest open bracket has been closed in the correct order and with the correct bracket type and that every type of close bracket has the same corresponding type of open bracket. This signifies to me that we should be using a FILO (First in last out) approach, i.e. the first open bracket has to be closed last. FILO suggests the usage of a stack.
Finding a solution in words
Let’s think of an intuitive approach to solving this problem.
- We would need to loop through the entire string.
- If we reach an open bracket we need to store it in the right order. i.e. we need to store it in a way that we keep the order in tack and have a way to access the latest open bracket
- If we reach a close bracket, we need to lookup the latest open bracket(as mentioned in point 2) and compare whether or not the closing bracket matches the latest open bracket, i.e.
)
matches(
,]
matches[
and}
matches{
.
The above seems to be a general solution to solve the problem. Now let’s think of edge cases.
- What if there are more open brackets than the corresponding close bracket?
- What if there are more closed brackets than corresponding open brackets?
A few of you keen eyed folks might also think of the case when the input is empty, i.e. “”. We do not have to worry about this case as the constraint is 1 <= s.length <= 10^4
. Regardless it is a good catch!
Transitioning words to coding terms
Now that we have the solution in english, let’s now think about what we need to solve this problem. We’ve mentioned earlier that we would need a way to keep track of the brackets in the right order, i.e. FILO. This suggests that we need a stack. The main methods of a stack is Push() and Pop(). Push pushes an element to the end of the stack and Pop retrieves and removes the last element of the stack. Exactly what we need.
Now for the problem of finding corresponding open/close bracket. We could make if else
statements each time to check if the open/close brackets matches correspondingly OR we could just make a mapping of the open and closing brackets, something like {'(':')', '[':']', '{':'}'}
which will make things more verbose.
Solution
Now that we have a plan of attack, let’s get to coding!
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function(s) {
// We have a mapping as mentioned before to check for corresponding brackets
const map = {'(':')', '[':']', '{':'}'}
// Have a stack of open brackets to keep track of
const openBrackets = []
for (let bracket of s) {
// If it is an open bracket, store it in our openBrackets stack
if (brackets === '(' || brackets === '[' || brackets === '{') {
openBrackets.push(brackets)
}
// If it is a closed bracket, check if it matches the corresponding latest open bracket
else {
const latestOpenBracket = openBrackets.pop()
if (brackets !== map[latestOpenBracket]) {
return false
}
}
}
// Our edge cases
// Check if openBracket stack is empty once our main logic is done
if (openBrackets.length === 0) {
return true
}
// return false if there are brackets that haven't been closed off
return false
};
Analysis
Let’s analyze our code, what is the time and space complexity of our solution.
Time complexity
- We have looped through the entire string once, this alone makes our solution
O(n)
. - We would have to loop through our
openBrackets
stack, which is worst caseO(n)
. i.e. in the case wheres
is all open brackets. - Lookup on mapping is
O(1)
.
Therefore from this we can say that the time complexity of our code is O(n)
.
Space complexity
- Our mapping is constant
O(1)
openBrackets
is worst caseO(n)
. i.e. in the case wheres
is all open brackets
Therefore, our space complexity is O(n)
.