package com.freetymekiyan.algorithms.level.medium;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* One way to serialize a binary tree is to use pre-order traversal. When we encounter a non-null node, we record the
* node's value. If it is a null node, we record using a sentinel value such as #.
* <p>
* _9_
* / \
* 3 2
* / \ / \
* 4 1 # 6
* / \ / \ / \
* # # # # # #
* For example, the above binary tree can be serialized to the string "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a
* null node.
* <p>
* Given a string of comma separated values, verify whether it is a correct preorder traversal serialization of a binary
* tree. Find an algorithm without reconstructing the tree.
* <p>
* Each comma separated value in the string must be either an integer or a character '#' representing null pointer.
* <p>
* You may assume that the input format is always valid, for example it could never contain two consecutive commas such
* as "1,,3".
* <p>
* Example 1:
* "9,3,4,#,#,1,#,#,2,#,6,#,#"
* Return true
* <p>
* Example 2:
* "1,#"
* Return false
* <p>
* Example 3:
* "9,#,#,1"
* Return false
* <p>
* Tags: Stack
*/
public class VerifyPreorderSerializationOfABinaryTree {
/**
* Stack.
* Iterate through the string characters.
* If it's a number, just push to stack.
* If it's a '#', we need to figure out some sub situations:
* 1) If the top of the stack is a number, then this '#' is the left child, just push it.
* 2) If the top of the stack is a '#', then this '#' is the right child, we should pop the subtree.
* 2.1) After the subtree is popped, if the stack top is still '#', it means the subtree should be popped again.
* 2.2) If the stack top is a number, we need to add a '#' to mark that the next node knows it's a right child.
* https://discuss.leetcode.com/topic/35973/java-intuitive-22ms-solution-with-stack
*/
public boolean isValidSerialization(String preorder) {
Deque<String> stack = new ArrayDeque<>();
String[] nodes = preorder.split(",");
for (int i = 0; i < nodes.length; i++) {
String curr = nodes[i];
while ("#".equals(curr) && !stack.isEmpty() && "#".equals(stack.peek())) {
stack.pop();
if (stack.isEmpty()) {
return false;
}
stack.pop();
}
stack.push(curr);
}
return stack.size() == 1 && "#".equals(stack.peek());
}
/**
* Degree.
* A value provide 2 out degrees and 1 in degree, except root.
* A '#' provide no out degree and 1 in degree.
* https://discuss.leetcode.com/topic/35976/7-lines-easy-java-solution
*/
public boolean isValidSerializationB(String preorder) {
String[] nodes = preorder.split(",");
int diff = 1;
for (String node : nodes) {
diff--;
if (diff < 0) {
return false;
}
if (!"#".equals(node)) {
diff += 2;
}
}
return diff == 0;
}
}