package com.freetymekiyan.algorithms.level.easy;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is
* valid.
* <p>
* The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.
* <p>
* Company Tags: Google, Airbnb, Facebook, Twitter, Zenefits, Amazon, Microsoft, Bloomberg
* Tags: Stack, String
* Similar Problems: (M) Generate Parentheses, (H) Longest Valid Parentheses, (H) Remove Invalid Parentheses
*/
public class ValidParentheses {
/**
* Stack.
* Use stack to check pair.
* Whenever there is a valid pair, pop from stack since it is already valid.
* Quick check: If string length not even, return false.
* Create a stack.
* For each character c in the string given:
* | If c is a left paren, push to stack.
* | Else if stack is not empty, and c matches with the peek:
* | Pop the left paren from stack.
* | Else return false.
* After the check, the stack should be empty because all pairs are popped.
* Otherwise return false.
*/
public boolean isValid(String s) {
if (s == null || s.length() == 0) {
return false;
}
if (s.length() % 2 != 0) { // String length must be even.
return false;
}
Deque<Character> stk = new ArrayDeque<>();
for (Character c : s.toCharArray()) {
if ("({[".indexOf(c) != -1) { // Push left parens.
stk.push(c);
} else if (!stk.isEmpty() && isMatch(stk.peek(), c)) {
stk.pop();
} else {
return false;
}
}
return stk.isEmpty();
}
private boolean isMatch(char c1, char c2) {
return (c1 == '(' && c2 == ')') || (c1 == '{' && c2 == '}') || (c1 == '[' && c2 == ']');
}
/**
* Stack.
* Push right parens onto stack instead of left ones.
* This way match function can be saved.
* When it is a right paren:
* | If the stack is empty, return false since there is no matching left.
* | If paren popped from stack is different from c, doesn't match, return false.
* Finally, return true if the stack is empty. Otherwise false.
*/
public boolean isValidB(String s) {
Deque<Character> stack = new ArrayDeque<>();
String left = "({[";
String right = ")}]";
for (char c : s.toCharArray()) {
int index = left.indexOf(c);
if (index != -1) { // Is left paren.
stack.push(right.charAt(index)); // Push right.
} else if (stack.isEmpty() || stack.pop() != c) {
return false;
}
}
return stack.isEmpty();
}
@Test
public void testExamples() {
Assert.assertTrue(isValid("()"));
Assert.assertTrue(isValid("()[]{}"));
Assert.assertFalse(isValid("([)]"));
Assert.assertTrue(isValid("[({(())}[()])]"));
Assert.assertFalse(isValid("a[a(a{a(a(.)a)a}x[a(a)v]w)q]z"));
}
}