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.
Java Solution
We can keep trimming the leaves until there is no one to remove. If a sequence is like “4 # #”, change it to “#” and continue. A stack is a good date structure for this purpose.
Here is an example:
public boolean isValidSerialization(String preorder) { LinkedList<String> stack = new LinkedList<String>(); String[] arr = preorder.split(","); for(int i=0; i<arr.length; i++){ stack.add(arr[i]); while(stack.size()>=3 && stack.get(stack.size()-1).equals("#") && stack.get(stack.size()-2).equals("#") && !stack.get(stack.size()-3).equals("#")){ stack.remove(stack.size()-1); stack.remove(stack.size()-1); stack.remove(stack.size()-1); stack.add("#"); } } if(stack.size()==1 && stack.get(0).equals("#")) return true; else return false; } |
If only stack operations are allowed, the solution can be written in the following way:
public boolean isValidSerialization(String preorder) { String[] arr = preorder.split(","); Stack<String> stack = new Stack<>(); for(String s: arr){ if(stack.isEmpty() || !s.equals("#")){ stack.push(s); }else{ while(!stack.isEmpty() && stack.peek().equals("#")){ stack.pop(); if(stack.isEmpty()){ return false; }else{ stack.pop(); } } stack.push("#"); } } return stack.size()==1 && stack.peek().equals("#"); } |
Oh, yes.. my bad…
This code will return true for this input [9,3,#,#,#]. Different values of diff will be : (0,+2,+3,+2,+1,0) => 0(true)
Try this one: [9,3,#,#,#], per your code is [0, +2, -1, -1, -1] = – 1 => fails, however the tree and the serialization are correct: [(root = 9): left = 3, right = #], [(node = 3): left = #, right = #]. If you move the [node=3] from the left side to the right side you get a fail again.
There is a better solution to this problem. For every non null node there is 2 out degrees and one in degree except root and for every leaf node there is one in-degree. So if we calculate the diff in degrees it shoud be zero for a valid preorder serialization. Code below:
public boolean isValidSerialization(String preorder) {
if(preorder == null || preorder.length() <= 0){
return true;
}
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;
}
The code above won’t work in case of “A, B, #, #, #” which is a valid serialization of a root node A with a left child B.
code is incorrect:
breaks for the case 9,3,4,#,2,#,#,1,#,#,6,8,#,#,#
code is wrong
93###.stops here
private static boolean verify(String s){
String arr[]=s.split(",");
Stack stack=new Stack();
if(arr.length==0 || arr[0]=="#") return true;
stack.push(0);
for(int i=1;i<arr.length;i++){
if(stack.size()==0) return false;
if(i!=stack.peek()+1){ stack.pop();}
if(arr[i].equals("#")){ continue;}
stack.push(i);
}
if(stack.size()!=0) return false;
return true;
}
Alternate solution:
boolean isValidPreorder(String serialization) {
String[] nodes = serialization.split(",");
return isValidPreorder(nodes, 0) == nodes.length;
}
int isValidPreorder(String[] nodes, int startIdx) {
if (startIdx >= nodes.length) return -1;
//end node
if (nodes[startIdx].equals("#")) return startIdx + 1;
//left branch
int nextIdx = isValidPreorder(nodes, startIdx + 1);
//right branch (note that it must exists to be a valid in order)
return nextIdx != -1? isValidPreorder(nodes, nextIdx) : -1;
}
Disclaimer: I don’t think I’m breaking the condition of “not reconstruct the tree” since I’m not doing it per-se.
this code is wrong.