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 #.
_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.
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.
Each comma separated value in the string must be either an integer or a character '#' representing null pointer.
You may assume that the input format is always valid, for example it could never contain two consecutive commas such as "1,,3".
Solution1:Stack
思路:
using a stack, scan left to right
case 1: we see a number, just push it to the stack
case 2: we see #, check if the top of stack is also #
(1) if so, pop #, recursively pop "c#" * n, and push a #
(2) if not, push this # to stack
实现1_a:原始思路
实现1_b:代码整理后
Time Complexity: O(N) Space Complexity: O(N)
Solution2:In/out degree
思路:
- For any graph sum of total indegree should be equal to total outdegree
- preorder 遍历时,整体累积的diff = outdegree - indegree,不会小于0。
Solution1_a Code:
public class Solution {
public boolean isValidSerialization(String preorder) {
// using a stack, scan left to right
// case 1: we see a number, just push it to the stack
// case 2: we see #, check if the top of stack is also #
// if so, pop #, recursively pop "c#" * n, and push a #
// if not, push this # to stack
// in the end, check if stack size is 1, and stack top is #
if (preorder == null) {
return false;
}
ArrayDeque<String> st = new ArrayDeque<>();
String[] strs = preorder.split(",");
for (int i = 0; i < strs.length; i++) {
String curr = strs[i];
// meet a number
if(!curr.equals("#")) {
st.push(curr);
}
// double #: meet # && stack top is #
// then RECURSIVELY backwards pop c#, finially push #
else if(curr.equals("#") && !st.isEmpty() && st.peek().equals("#")) {
while(curr.equals("#") && !st.isEmpty() && st.peek().equals("#")) {
st.pop(); // pop #
if (st.isEmpty()) return false; // check
st.pop(); // pop number
}
st.push("#");
}
// meet # && stack top is not #
else {
st.push(curr);
}
}
return st.size() == 1 && st.peek().equals("#");
}
}
Solution1_b Code:
public class Solution {
public boolean isValidSerialization(String preorder) {
// using a stack, scan left to right
// case 1: we see a number, just push it to the stack
// case 2: we see #, check if the top of stack is also #
// if so, pop #, recursively pop "c#" * n, and push a #
// if not, push this # to stack
// in the end, check if stack size is 1, and stack top is #
if (preorder == null) {
return false;
}
ArrayDeque<String> st = new ArrayDeque<>();
String[] strs = preorder.split(",");
for (int i = 0; i < strs.length; i++) {
String curr = strs[i];
// double #: meet # && stack top is #
// then RECURSIVELY backwards pop c#, finially push #
while(curr.equals("#") && !st.isEmpty() && st.peek().equals("#")) {
st.pop(); // pop #
if (st.isEmpty()) return false; // check
st.pop(); // pop number
}
// (1) #, with stack top #: push # after recursive pop
// (2) or meet a number: push that number
// (3) or meet && stack top is not #: push #
// all same, we can just:
st.push(curr);
}
return st.size() == 1 && st.peek().equals("#");
}
}
Solution2 Code:
class Solution {
public boolean isValidSerialization(String preorder) {
String[] nodes = preorder.split(",");
int diff = 1;
for (String node: nodes) {
diff--;
if (diff < 0) return false;
if (!node.equals("#")) diff += 2;
}
return diff == 0;
}
}