Need to find open and closed bracket, if the sequence of opening and closing brackets is violated, then return false.
But if don't revert right array to compare with left array, i don't make check brackets here {[(3+1)+2]+}. And if reverse like now, then i fail to check here [1+1]+(2*2)-{3/3}
function brackets(expression){
let leftArr=[];
let rightArr = [];
for(let i=0; i<expression.length; i++){
if(expression[i] === '(' || expression[i] === '[' || expression[i] === "{"){
leftArr.push(expression[i]);
}
if(expression[i] === ')'){
rightArr.push("(");
}else if(expression[i] === '}'){
rightArr.push("{");
} else if(expression[i] === ']'){
rightArr.push("[");
}
}
rightArr.reverse();
if(leftArr.length<rightArr.length || leftArr.length>rightArr.length){
return false;
}
for(let k=0; k<leftArr.length; k++) {
if(leftArr[k] != rightArr[k]){
return false;
}
}
return true;
}
console.log(brackets('(3+{1-1)}')); // false
console.log(brackets('{[(3+1)+2]+}')); //true
console.log(brackets('[1+1]+(2*2)-{3/3}')); //true
console.log(brackets('(({[(((1)-2)+3)-3]/3}-3)')); //false
In the shortest possible, with comments for lines that are probably confusing for you.
function check(expr){
const holder = []
const openBrackets = ['(','{','[']
const closedBrackets = [')','}',']']
for (let letter of expr) { // loop trought all letters of expr
if(openBrackets.includes(letter)){ // if its oppening bracket
holder.push(letter)
}else if(closedBrackets.includes(letter)){ // if its closing
const openPair = openBrackets[closedBrackets.indexOf(letter)] // find its pair
if(holder[holder.length - 1] === openPair){ // check if that pair is the last element in the array
holder.splice(-1,1) // if so, remove it
}else{ // if its not
holder.push(letter)
break // exit loop
}
}
}
return (holder.length === 0) // return true if length is 0, otherwise false
}
check('[[{asd}]]') /// true
Right now you are getting every single open bracket into one array, then pushing an open bracket for every closing one into another array, then comparing them. That's a bit wasteful.
Instead, you can maintain a stack. Push an open tag onto the stack and if you find a close bracket - pop from the stack
if there is no match or nothing on the stack when you pop, terminate with a failure
if you finish with a stack size of zero, then you are successful
function brackets(expression) {
let stack = [];
let current;
const matchLookup = {
"(": ")",
"[": "]",
"{": "}",
};
for (let i = 0; i < expression.length; i++) {
current = expression[i]; //easier than writing it over and over
if (current === '(' || current === '[' || current === "{") {
stack.push(current);
} else if (current === ')' || current === ']' || current === "}") {
const lastBracket = stack.pop();
if (matchLookup[lastBracket] !== current) { //if the stack is empty, .pop() returns undefined, so this expression is still correct
return false; //terminate immediately - no need to continue scanning the string
}
}
}
return stack.length === 0; //any elements mean brackets left open
}
console.log(brackets('(3+{1-1)}')); // false
console.log(brackets('{[(3+1)+2]+}')); //true
console.log(brackets('[1+1]+(2*2)-{3/3}')); //true
console.log(brackets('(({[(((1)-2)+3)-3]/3}-3)')); //false
I have used an object to lookup the values but it need not be one. An alternative is to use two arrays that you have to keep in sync
opening = ["(", "[", "{"]
closing = [")", "]", "}"]
On the other hand, if you have those, you can shorten your if checks to if (open.includes(current)) and if (closing.includes(current)).
This can be an easier solution:
const checkBrackets = (expression) => {
const stack = [];
const bracketLookup = {
'{': '}',
'(': ')',
'[': ']',
};
for (const key of expression) {
if(Object.keys(bracketLookup).includes(key)) { // matches open brackets
stack.push(key);
} else if(Object.values(bracketLookup).includes(key)) { //matches closed brackets
const lastBracket = stack.pop();
if(bracketLookup[lastBracket] !== key) {
return false;
}
}
}
return stack.length === 0;
}
Results:
checkBrackets('a(fg(a)}'); // false
checkBrackets('[1+1)+(2*2]-{3/3}'); // false
checkBrackets('a(d-h)+y{hh}||[hh-a-]'); // true
You can use stack with switch statement with a single for loop for efficient time and space complexity
function checkParantesis(str) {
const stack = [];
for (let s of str) {
if (s == '(' || s == '[' || s == '{') {
stack.push(s);
continue;
}
if (stack.length === 0) {
return false
}
switch (s) {
case ')':
stack.pop();
if (s == '{' || s == '[') {
return false
}
break;
case '}':
stack.pop();
if (s == '(' || s == '[') {
return false
}
break;
case ']':
stack.pop();
if (s == '{' || s == '(') {
return false
}
break;
}
}
return stack.length ? false : true
}
const output = checkParantesis('{{}}'));
console.log(output)
You can use the function String.prototype.replace to gather the brackets and use a kind of stack to compare each char. The stack is useful in order to know what was the last pushed bracket.
let check = (e) => {
let brackets = [],
stack = [],
map = {'}': '{', ']': '[', ')': '('};
e.replace(/[\[\]\{\}\(\)]/g, (m) => m && brackets.push(m));
for (let i = 0, {length} = brackets; i < length; i++) {
if (['}', ']', ')'].includes(brackets[i])) {
if (stack.pop() !== map[brackets[i]]) return false;
} else stack.push(brackets[i]);
}
return !stack.length;
};
console.log(check('(3+{1-1)}')); // false
console.log(check('{[(3+1)+2]+}')); //true
console.log(check('[1+1]+(2*2)-{3/3}')); //true
console.log(check('(({[(((1)-2)+3)-3]/3}-3)')); //false
I hope this will solve your problem...
function brackets(expression) {
let leftArr=[];
for(let i=0; i<expression.length; i++) {
if(expression[i] === '(' || expression[i] === '[' || expression[i] === "{") {
leftArr.push(expression[i]);
}
let leftArrLength = leftArr.length;
if(expression[i] === ')' && leftArr[leftArrLength - 1] === '('){
leftArr.pop();
}else if(expression[i] === '}' && leftArr[leftArrLength - 1] === '{') {
leftArr.pop();
} else if(expression[i] === ']' && leftArr[leftArrLength - 1] === '[') {
leftArr.pop();
}
else if(expression[i] === ')' || expression[i] === '}' || expression[i] === ']'){
return false;
}
}
return leftArr.length === 0;
}
console.log(brackets('(3+{1-1)}')); // false
console.log(brackets('{[(3+1)+2]+}')); //true
console.log(brackets('[1+1]+(2*2)-{3/3}')); //true
console.log(brackets('(({[(((1)-2)+3)-3]/3}-3)')); //false
console.log(brackets('(((([[[[{{{3}}}]]]]))))')); //false
My approach will be a little different.
These bracket pairs lie in the ASCII pair right after there first occurence.
Means '(' is placed (at 41) after ')' (at 40).
So, if there is a string input {[()]} and are in order.
We can divide the string by length/2 and check for ASCII value + 1
I think this the best solution.
const checkBracketSequenceBalance = (exp) => {
const pairs = {
'(': ')',
'[': ']',
'{': '}'
},
open = []
for (let i = 0; i < exp.length; i++)
if (pairs[exp[i]])
open.push(exp[i])
else if (exp[i] === pairs[open[open.length - 1]])
open.pop()
return !open.length
}
var input = "[({([])})]";
console.log(checkPairs(input));
function checkPairs(input=null) {
var arr = input.split("");
var result = false;
var tmpArr = [];
if ((arr.length % 2) == 0) {
arr.forEach(element => {
if (tmpArr[element] == null) {
tmpArr[element] = 1;
} else {
tmpArr[element] += 1;
}
});
if (tmpArr['['] == tmpArr[']'] && tmpArr['('] == tmpArr[')'] && tmpArr['{'] == tmpArr['}']) {
result = true;
}
}
return result;
}
Related
Trying to solve a problem at LeetCode called "Valid Parentheses".
Conditions are:
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.
I wrote a function and it's working in this snippet:
let arr = ['()']
var isValid = function (data) {
let stack = [];
const bracketsArray = {
'{':'}',
'[':']',
'(':')'
}
for (i=0; i < data[0].length; i++) {
if (data[0][i] == '{' || data[0][i] == '(' || data[0][i] == '[') {
stack.push(data[0][i]);
} else if (data[0][i] == '}' || data[0][i] == ']' || data[0][i] == ')') {
if (bracketsArray[stack[stack.length-1]] == data[0][i]) {
stack.pop()
}
}
}
if (stack.length == 0) {
return true
} else {
return false
}
}
console.log(isValid(arr))
Function gives a correct output (boolean)
But when I run this code at LeetCode for some reason the same code gives me a wrong boolean.
Don't understand what is wrong.
/**
* #param {string} s
* #return {boolean}
*/
var isValid = function(s) {
let stack = [];
const bracketsArray = {
'{':'}',
'[':']',
'(':')'
}
for (i=0; i < s[0].length; i++) {
if (s[0][i] == '{' || s[0][i] == '(' || s[0][i] == '[') {
stack.push(s[0][i]);
} else if (s[0][i] == '}' || s[0][i] == ']' || s[0][i] == ')') {
if (bracketsArray[stack[stack.length-1]] == s[0][i]) {
stack.pop()
}
}
}
if (stack.length == 0) {
return true;
} else {
return false;
}
};
Any advice?
On LeetCode the function parameter is a string, but in your tests you are passing an array, and also your function code expects an array, since it accesses the string with s[0], instead of s.
Unrelated, but:
Your code fails when the input is just a closing bracket. This is because your loop doesn't break with return false when a non-matching closing bracket is encountered. This should happen in the else part of if (bracketsArray[stack[stack.length-1]] == s[i]) {
Don't use an undeclared variable i, which will then implicitly become a global variable (if running in non-strict mode).
Don't name your variable bracketsArray since it is not an array.
Make more use of that object, instead of making three comparisons with opening brackets.
The final if...then is overkill for just returning the value of a boolean expression.
So:
var isValid = function(s) {
const stack = [];
const brackets = {
'{':'}',
'[':']',
'(':')'
}
const closing = Object.values(brackets);
for (let ch of s) {
if (brackets[ch]) {
stack.push(brackets[ch]);
} else if (ch == stack.at(-1)) {
stack.pop()
} else if (closing.includes(ch)) {
return false;
}
}
return !stack.length;
};
console.log(isValid("{([])}")); // true
console.log(isValid("]")); // false
The way you are accessing the current character of the iteration is wrong. Instead of doing s[0][i], simply do s[i].
s[0][i] accesses the first character, and then attempts to get the i-th entry from it (which is undefined).
var isValid = function(s) {
let stack = [];
const bracketsArray = {
'{':'}',
'[':']',
'(':')'
}
for (i=0; i < s.length; i++) {
if (s[i] == '{' || s[i] == '(' || s[i] == '[') {
stack.push(s[i]);
} else if (s[i] == '}' || s[i] == ']' || s[i] == ')') {
if (bracketsArray[stack[stack.length-1]] == s[i]) {
stack.pop()
}
}
}
if (stack.length == 0) {
return true;
} else {
return false;
}
};
isValid("{([])}") // true
isValid("{([)}") // false
I'm working on a coding challenge that involves valid parenthesis and I'm trying to troubleshoot why it's not giving me the intended response.
function isValid(str) {
if (str.length === 0)
return true
let matchingOpeningBracket, char
let stack = []
let openingBrackets = ['[', '<', '(']
let closingBrackets = [']', '>', ')']
for (let i = 0; i < str.length; i++) {
char = str[i]
if (closingBrackets.indexOf(char) > -1) {
matchingOpeningBracket = openingBrackets[closingBrackets.indexOf(char)]
if (stack.length == 0 || (stack.pop() != matchingOpeningBracket)) {
return false
}
} else {
stack.push(char)
}
}
return (stack.length == 0)
};
When I try to check console.log(isValid('---(++++)---')) and console.log(isValid('before(middle[])after')) it gives me a false value but it should be passing as true according to the challenge key. I'm not sure what step I'm missing. The other tests examples are logging as intended as seen here except for the first 2.
//true // returns false
// let example1 = ("before(middle[])after")
//true //returns false
// let example1 = ("---(++++)---")
//true
// let example1 = ("")
//false
// let example1 = (")(")
//false
// let example1 = ("<(>)")
//true
// let example1 = ("([<>()])")
//false
// let example1 = ("([)")
You are pushing everything that is not a closing bracket onto the stack when you should ignore chars that are neither opening or closing brackets. Change your else condition to this:
else if (openingBrackets.indexOf(char) > -1) {
I definitely would not want to complicate things so I am giving a simple solution, so if you see it fit you can use it :)
function isValid(str) {
if (str.length === 0)
return true
let char;
let stack = [];
let openingBrackets = ['[', '<', '(']
let closingBrackets = [']', '>', ')']
matchesOpen = (val) => (val === '[' || val === '<' || val === '(')
matchesclose = (val) => (val === ']' || val === '>' || val === ')')
getOpeningBracket = (val) => {
switch (val) {
case ']':
return '[';
case ')':
return '(';
case '>':
return '<';
default:
return '';
}
}
for (let i = 0; i < str.length; i++) {
char = str[i]
if (matchesOpen(char)) {
stack.push(char);
} else if (matchesclose(char)) {
if (stack.pop() !== getOpeningBracket(char)) return false;
}
}
return (stack.length == 0)
};
console.log(isValid(('---(++++)---')))
console.log(isValid('before(middle[])after'))
console.log(isValid("---(++++)---"))
You’re pushing onto the stack every char that is not an opening parenthesis. You only want to push opening parentheses onto the stack.
Notice that you get a false result whenever there are non-parenthesis characters in the string.
There is a challenge on codewars that asks you to check whether a string of parentheses, brackets, and curly braces is valid.
A string of braces is considered valid if all braces are matched with the correct brace.
I.e. "()" is valid and "[(])" is not.
"(){}[]" is valid and "[({})](]" is not. Etc.
I've been able to create some logic to check for whether or not there are the right number of opening and closing braces.
ATTEMPT:
function validBraces(braces) {
let parenCount = 0;
let squareBracketCount = 0;
let curlyBraceCount = 0;
for (let i =0; i < braces.length; i++) {
let character = braces[i];
if (character === "(") {
parenCount -= 1;
}
if (character === ")") {
parenCount += 1;
}
if (character === "[") {
squareBracketCount -= 1;
}
if (character === "]") {
squareBracketCount += 1;
}
if (character === "{") {
curlyBraceCount -= 1;
}
if (character === "}") {
curlyBraceCount += 1;
}
}
if (parenCount === 0 && squareBracketCount === 0 && curlyBraceCount === 0) {
return true;
}
else {
return false;
}
}
But I've not been able to come up with a way to check for whether or not the opening brace "closes" before the next type of brace opens.
Maybe something like this?
if (
(firstChar === "(" && lastChar === ")") ||
(firstChar === "{" && lastChar === "}") ||
(firstChar === "[" && lastChar === "]")
) {
return true;
} else {
return false;
}
But then this would have to be checked in accordance with my other if-statement...(?)
EDIT: Key to understanding this challenge is that the closing brace must either come directly after the opening brace or it must be "parallel" - in symmetry with the other.
You don't really need to use arrays here, you can just use regex and recursion:
const regex = /\(\)|\[\]|\{\}/;
const validBraces = braces => regex.test(braces)
? validBraces(braces.replace(regex, ''))
: '' === braces
console.log(validBraces('{{}}')) // true
console.log(validBraces('{{[]}}')) // true
console.log(validBraces('{[{}]}')) // true
console.log(validBraces('({{}})')) // true
console.log(validBraces('{[()]}')) // true
console.log(validBraces('{{}[}')) // false
console.log(validBraces('{{]}}')) // false
console.log(validBraces('{}}')) // false
console.log(validBraces('{({}}')) // false
console.log(validBraces('((}}')) // false
console.log(validBraces('}[)}')) // false
You can use array to keep track of previously appeared opening braces and once any closing tag appears you need to match it with the last value of array if it's matching pop the last value out of else else return false, in the end if you're left with empty array return true else return false
function validBraces(braces){
let tracer = []
for(let i=0;i < braces.length; i++){
if ( braces[i] === "(" || braces[i] === "{" || braces[i] === "["){
tracer.push(braces[i])
} else{
if(tracer.length === 0) return false
let lastValue = tracer[tracer.length-1]
if( (braces[i] === ']' && lastValue === '[') || (braces[i] === '}' && lastValue === '{') || (braces[i] === ')' && lastValue === '('))
{
tracer.pop()
} else {
break;
}
}
}
return tracer.length === 0
}
console.log(validBraces( "()" )) // true
console.log(validBraces( "[]" )) // true
console.log(validBraces( "{}" )) // true
console.log(validBraces( "(){}[]" )) // true
console.log(validBraces( "([{}])" )) // true
console.log(validBraces( "(}" )) // false
console.log(validBraces( "[(])" )) // false
console.log(validBraces( "({})[({})]" )) // true
console.log(validBraces( "(})" )) // false
console.log(validBraces( "(({{[[]]}}))" )) //true
console.log(validBraces( "{}({})[]" )) // true
console.log(validBraces( ")(}{][" )) // false
console.log(validBraces( "())({}}{()][][" )) // false
console.log(validBraces( "(((({{" )) // false
console.log(validBraces( "}}]]))}])" )) // false
In scala you can do this
object Kata {
def validBraces(s: String): Boolean =
s.replace("()", "").replace("[]", "").replace("{}", "") match { case "" => true; case `s` => false; case x => validBraces(x) }
}
function validBraces(braces){
while(/\(\)|\[\]|\{\}/g.test(braces)){braces = braces.replace(/\(\)|\[\]|\{\}/g,"")}
return !braces.length;
}
// double regex
My JavaScript solution of this kata is simple to understand and passes all tests. Yet im aware its optimization isn't top-notch. It simply eliminates elements step by step:
Start: ( { [] } ) || ( { [] } }
Then: ( {} ) || ( {} }
Then: () || (}
Finish: clear || leftovers
When length = 0 it passes, and when length > 0 it wont
function validBraces(braces){
while(braces.indexOf("{}") !== -1 || braces.indexOf("()") !== -1 || braces.indexOf("[]") !== -1){
braces = braces.replace("{}", "").replace("()", "").replace("[]", "");
}
return braces.length === 0 ? true: false;
console.log(validBraces("(({{[[]]}}))"));
I have done it in Scala with some tests and it works. In case the string's length is 2 if dont need to enter the recursive call because in the match you have already checked if it correct or not :
object Kata1{
def validBraces(s: String): Boolean ={
var valid: Boolean = true
if(s.length > 1){
s(0) match{
case '(' => if( s(1) == ')' || s(s.length-1) == ')'){
if(s.length != 2){
if(s(1) == ')'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf(')') != -1){
var newS = s.substring(0, s.indexOf(')')).concat(s.substring(s.indexOf(')')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case '[' => if( s(1) == ']' || s(s.length-1) == ']') {
if(s.length != 2){
if(s(1) == ']'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf(']') != -1){
var newS = s.substring(0, s.indexOf(']')).concat(s.substring(s.indexOf(']')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case '{' => if( s(1) == '}' || s(s.length-1) == '}') {
if(s.length != 2){
if(s(1) == '}'){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}
} else {
if(s.lastIndexOf('}') != -1){
var newS = s.substring(0, s.indexOf('}')).concat(s.substring(s.indexOf('}')+1, s.length))
valid = validBraces(newS.substring(1, s.length-1))
}else valid = false
}
case _ => valid = false
}
/*if(s.length != 2 && valid){
if(s(1) == ')' || s(1) == '}' || s(1) == ']' ){
valid = validBraces(s.substring(2, s.length))
}else{
valid = validBraces(s.substring(1, s.length-1))
}
}*/
}else{
valid = false
}
if(s.length == 0){
valid = true
}
valid
}
}
Kata1.validBraces("()") //true
Kata1.validBraces("[()]") //true
Kata1.validBraces("[(])") //false
Kata1.validBraces("([{}])") //true
Kata1.validBraces("([{]})") //false
Kata1.validBraces("{({{()}({}())})}")//true
Kata1.validBraces("({]}{")//false
I have written the logic to check for parenthesis for "(" and ")" but there seems to an issue when parenthesis gets mixed. This is because I'm just comparing the total parenthesis count.
This is what i wrote
function checkParanthesis(str){
var depth=0;
for(var i in str){
if(str[i] == "(" || str[i] == "{" || str[i] == "[")
depth++;
else if(str[i] == ")" || str[i] == "}" || str[i] == "]")
depth--;
}
if(depth !==0) return false;
return true;
}
console.log(checkParanthesis("() test"));
Question:
But how can I check for multiple parenthesis elements? (){}[]
For example,
Input:
"[(]) abcd" // should return false
"[{()}] test" // should return true
Should return false (Not true)
Use an array as a stack to keep track of unresolved opening braces:
function checkParanthesis(str){
var stack=[];
for(var i=0; i<str.length; i++){
if(str[i] == "(" || str[i] == "{" || str[i] == "[")
stack.push(str[i]);
else if(str[i] == ")") {
if(stack.pop() != "(") { return false; }
}
else if(str[i] == "}") {
if(stack.pop() != "{") { return false; }
}
else if(str[i] == "]") {
if(stack.pop() != "[") { return false; }
}
}
return !stack.length;
}
You can probably clean this up to be more readable, but basically:
Every time you find an opening brace, add it to the stack.
Every time you see a closing brace, pop the stack and see if the stack's top is a matching opening brace.
If it's not, you have a mismatch, so you can immediately return false.
If you make it to the end, you didn't spot any errors, return true if the stack is empty (i.e., stack.length is 0).
(Note I also changed your i in str loop since it will iterate over properties on String.prototype.)
One cleanup you could do (but I'm not sure if this makes the code more readable or not) would be to put the brace pairings in an object, with the closing character as the key and the corresponding opening character as the value. Then, see if the current character exists as a key in the object, and if so, pop the stack and see if the value for that key matches:
function checkParanthesis(str){
var stack=[];
var brace_pairings = { ")":"(", "}":"{", "]":"[" };
for(var i=0; i<str.length; i++){
if(str[i] == "(" || str[i] == "{" || str[i] == "[") {
stack.push(str[i]);
} else if(str[i] in brace_pairings) {
if(stack.pop() != brace_pairings[str[i]]) { return false; }
}
}
return !stack.length;
}
Rather than a counter, you could use a stack, pushing a token onto the stack when an opening bracket is seen, and popping from the stack when the correct closing bracket is seen. If a closing bracket is encountered when a different type of bracket is at the top of the stack, or when the stack is empty, the string is unbalances.
Something like this (not polished and tested):
function checkParanthesis(str){
var stack = [];
var open;
for(var i in str){
if(str[i] == "(" || str[i] == "{" || str[i] == "[") {
stack.push(str[i]);
}
else if(str[i] == ")" || str[i] == "}" || str[i] == "]") {
if ( stack.length == 0 ) {
return false;
}
open = stack.pop();
if (
( open == '(' && str[i] != ')' )
|| ( open == '[' && str[i] != ']' )
|| ( open == '{' && str[i] != '}' )
) {
return false;
}
}
}
if ( stack.length > 0 ) {
return false;
}
return true;
}
Use a regex to get all the braces in a match() array...then remove each end of array testing each set
function checkParanthesis(str) {
//hashmap to compare open/close braces
var closers = {'[': ']','(': ')','{': '}'};
// create braces array
var parStack = str.match(/\(|\{|\[|\)|\}|\]/g) || [];
if (parStack.length % 2 !== 0) {//must have even number
return false;
} else {
while (parStack.length) {
// check each end of array against each other.
if (closers[parStack.shift()] !== parStack.pop()) {
//mismatch , we're done
return false;
}
}
return true;
}
}
console.log('no braces ', checkParanthesis("test"));
console.log('matched ', checkParanthesis("() test"));
console.log('mis matched ',checkParanthesis("[(]) abcd")); // should return false
console.log('matched ',checkParanthesis("[{()}] test"));
The array/stack/counter approach reads the string from left to right. Another approach is to work from the inside out.
function checkParanthesis(str){
while ( str.indexOf('()')>=0 || str.indexOf('[]')>=0 || str.indexOf('{}')>=0 ) {
str = str.replace('()','').replace('[]','').replace('{}','');
}
return str.length===0;
}
You could use regular expressions for the replace part to do a global replace and loop fewer times. The downside is that you'd need to escape everything in sight: str.replace(/\(\)/g,'') et.c.
Since I was working on leetCode and find your question, I found this article was written pretty clear about the problem and I tested it and I quoted here:
Click here!
Parenthesis Matching Problem in JavaScript
let isMatchingBrackets = function (str) {
let stack = [];
let map = {
'(': ')',
'[': ']',
'{': '}'
}
for (let i = 0; i < str.length; i++) {
// If character is an opening brace add it to a stack
if (str[i] === '(' || str[i] === '{' || str[i] === '[' ) {
stack.push(str[i]);
}
// If that character is a closing brace, pop from the stack, which will also reduce the length of the stack each time a closing bracket is encountered.
else {
let last = stack.pop();
//If the popped element from the stack, which is the last opening brace doesn’t match the corresponding closing brace in the map, then return false
if (str[i] !== map[last]) {return false};
}
}
// By the completion of the for loop after checking all the brackets of the str, at the end, if the stack is not empty then fail
if (stack.length !== 0) {return false};
return true;
}
The Function to check mathematical expression not working.
I debugged this on chrome, and i saw that when it gets to the first pop (stack.pop()!== chars[i]), it returns false, but it shouldn't.
var smarter_validate = function(str) {
var chars = str.split('');
var stack = [];
var lookup = {
'(': ')',
'[': ']',
'{': '}',
'<': '>'
};
var left = Object.keys(lookup);
var right = Object.keys(lookup).map(function(key) {
return lookup[key]
});
for (var i = 0; i < chars.length; i++) {
if (left.indexOf(chars[i]) !== (-1)) {
stack.push(chars[i]);
} else if (right.indexOf(chars[i]) !== (-1)) {
if ((stack.length === 0) || (stack.pop() !== chars[i])) {
return false;
}
}
}
return (stack.length === 0);
};
console.log("SMART VALIDATE" + smarter_validate('(3+4[*2{6+8}])'));
You actually have to compare the popped value's corresponding closing character with chars[i], not the popped value itself.
So you need to do
if (stack.length === 0 || lookup[stack.pop()] !== chars[i]) {
Now, when you { from the stack, you will look for the corresponding closing character from the lookup and compare it with the current closing character.
Alternatively you can simply push the expected closing character in the stack so that you don't have do the lookup during the comparison, like this
stack.push(lookup[chars[i]]);