Saturday, April 23, 2016

Today we improve the performance of the previous code sample shown to reconstruct the tree from the preorder and inorder traversals.
The key to improving performance is that we do that many steps as it takes to rebuild the tree and as cheaply as possible. while this might sound cliched, it may translate to our problem this way. Are there any redundant operations in the previous code shown ? The answer is yes, We do repeated Array.IndexOf ? How do we avoid this?
Because we deal with a tree, we know all test cases can be covered by the elementary tree with a single node and two siblings where one or more nodes can be null.
Consequently, we take node J as root with left K and Right L
we have

1) Both siblings:
Pre: JKL
In: KJL
2) Right sibling only:
Pre: JL
In: JL
3) Left Sibling only
Pre: JK
In: KJ

When the siblings are trees
4) No leftchild:
Pre: J some-other-node
In: J  intermediary-nodes some-other-node
5) No right child:
Pre:  J some-other-node
In: some-other-node  intermediary-nodes J


Therefore we can use relative positions and indexes instead of absolute indexes to optimize the solution. We make the following observations:
The next element to a node in preorder has an index lesser than its own in the in order and this implies the next element is a left child.
The next element to a node has an immediate next index in the inorder as well then the next element is a right child
The next element to a node has an index greater than its own + 1, then it has no right child.
The previous element to a node in pre order occurs as the next element in the in order means that the node has no left child

Node Rebuild(List<Node> pre, List<node> in) // All nodes in list initialized with left and right = NULL and set only with data
{
assert( pre != NULL && in != null);
assert (pre.Count() == in.Count());

for(int i = 0; i < pre.Length; i++)
{
Node root = pre[i];
int inIndex= Array.indexOf(in, pre[i]);
if (i+1 < pre.Length && inIndex+1<in.Length)
{
//todo:
//set root.left
bool left = true;
for (int j =inIndex; j< in.Count(); j++)
     if (in[j] == pre[i+1])
       left = false;
if(left != false)
  root.left = pre[i+1];
//set root.right
bool right= true;
for (int j =inIndex; j>= 0 j--)
     if (in[j] == pre[i+1])
       right = false;
if(right != false){
   Node target = in[inIndex-1];
   for(int j =i+1; j<pre.Count();j++)
    if (pre[j] == target)
        root.right = pre[j];
}
}
}

return pre[0];
}

Some can claim that yesterday's approach was development oriented and today's approach is test-oriented and there may be some truth in that there are entrenched mindsets along those lines but the reality is that today's approach is leaned on for real world data.

No comments:

Post a Comment