Reputation: 81
Given a string containing just the characters '('
, ')'
, '{'
, '}'
, '['
and ']'
, determine if the input string is valid.
An input string is valid if:
Example 1:
Input: "()[]{}"
Output: true
Example 2:
Example 2:
Input: "{[(])}"
Output: false
My solution for the above problem is:
static boolean isPair(char left,char right){
return left=='{' && right=='}' || left=='(' && right==')' || left=='[' && right==']';
}
public boolean isValid(String s) {
Stack<Character> stack= new Stack<>();
for(char ch: s.toCharArray()){
if(ch=='(' || ch=='{' || ch=='['){
stack.push(ch);
}
else{
if(!stack.isEmpty() && isPair(stack.peek(),ch))
stack.pop();
else
return false;
}
}
return stack.isEmpty();
}
I have found a much smarter solution somewhere but unable to understand it. Here's the code:
public boolean isValid(String s) {
Stack<Character> stack= new Stack<>();
for(char ch: s.toCharArray()){
if(ch=='(')
stack.push(')');
else if(ch=='{')
stack.push('}');
else if(ch=='[')
stack.push(']');
else if(stack.isEmpty() || stack.pop()!=ch)
return false;
}
return stack.isEmpty();
}
Please help me to understand the working of last else-if
block.
Upvotes: 2
Views: 6992
Reputation: 31
I am adding my code here using map in JavaScript, Please add if you find a way better than it.
` var isValid = function(s) {
let map={
")":"(",
"]":"[",
"}":"{"
}
let _stack = [];
for(let i=0;i<s.length;i++)
{
if(s[i]==="(" || s[i]==="[" || s[i]==="{")
{
_stack.push(s[i]);
}
else if(_stack[_stack.length-1]===map[s[i]])
{
_stack.pop();
}
else
return false;
}
return _stack.length?false:true;
};
`
Upvotes: 0
Reputation: 1231
Javascript solution to the problem
var isValid = function (s) {
if (s.length % 2 !== 0) return false
// Stack to store left symbols
const leftSymbols = [];
// Loop for each character of the string
for (let i = 0; i < s.length; i++) {
// If left symbol is encountered
if (s[i] === '(' || s[i] === '{' || s[i] === '[') {
leftSymbols.push(s[i]);
}
// If right symbol is encountered
else if (s[i] === ')' && leftSymbols.length !== 0 && leftSymbols[leftSymbols.length - 1] === '(') {
leftSymbols.pop();
} else if (s[i] === '}' && leftSymbols.length !== 0 && leftSymbols[leftSymbols.length - 1] === '{') {
leftSymbols.pop();
} else if (s[i] === ']' && leftSymbols.length !== 0 && leftSymbols[leftSymbols.length - 1] === '[') {
leftSymbols.pop();
}
// If none of the valid symbols is encountered
else {
return false;
}
}
return leftSymbols.length === 0;
};
Upvotes: 0
Reputation: 2932
It is actually pretty similar to your own version.
The main difference is that you push the open brackets to the stack and in isPair
check if the open bracket on top of the stack matches the closing one you're currently evaluating.
That solution skips it by directly pushing the expected closing bracket to the stack, but functionally it's the same.
That last if else
does the exact same than your else
:
stack.isEmpty()
returns falseThere is a slight difference that for case 2 that solution pops the stack while in yours you don't pop it. But it doesn't change anything as the function returns and that stack will not be used anymore.
Upvotes: 0
Reputation: 13057
You have pushed the closing bracket
for all the opening
brackets. So, that when closing brackets come, then it will match the character at the top of stack. If it doesn't match or stack becomes empty. That means unbalanced.
else if(stack.isEmpty() || stack.pop()!=ch)
return false;
When you reach here, you have a bracket
as ch but the stack is empty or the value from the stack doesn't match the incoming character.
So, the parantheses are not balanced.
Upvotes: 2