views:

443

answers:

1

I have these 2 sequences for a binary tree (not a BSD):
InOrder: 3 2 1 4 5 7 6
PostOrder: 3 1 2 5 6 7 4

We know that the last element in postOrder is the root, so we locate the root at the inOrder sequence and subdivide like this:
- all the elements at the left of the root go to the left subtree
- all the elements at the right of the root go to the right subtree Moreover, the order which they appear in the tree is given by the postOrder.

For this example: 4 = root

Left-subtree (in-order): 3 2 1 Right-subtree (in-order): 5 7 6
Left-subtree (post-order): 3 1 2 Right-subtree (post-order): 5 6 7

We do the same, recursively ... so, I think the tree reconstructed is:

              4
         2         7
      3     1    5   6

I want to return only the leaf that leads to the shortest path(sum); I do not need to reconstruct the tree and then traverse it and do a shortest path. I just need the leaf which leads me to the minimum sum. In this case I have 4 possible paths: 4+2+3=9 || 4+2+1 = 7 || 4+7+5 = 16 || 4+7+6 = 17, as the less is 7, I have to return the leaf 1.

I think the algo is pretty simple, but I have difficult writing recursive code for it ...

Could someone please help a noob? C, Java, C++ or Python ... I don't mind

+1  A: 

Hi,

if you have an in-order traversal and a post-order traversal for a general binary tree, they don't even define the tree uniquely if you can have duplicated values, e.g. the sequence [1,1,1] for both post-order and in-order can be one of the following trees:

    1      1
   1 1      1
             1

And the minimum-sum path has sum of 2 on the left and the sum of 3 on the right.

So assume all the values are distinct.

Suppose you have a post-order traversal list [x1,x2,...,xn] and in-order traversal list [y1,...,yk,...,yn] so that xn==yk. Because xn is the root of the tree, you know now that [y1,...,yk-1] is the left subtree and [yk+1,...,yn] is the right subtree. The left subtree is then also represented by [x1,...,xk-1] because the size of the left subtree is obviously constant, so you can divide the post-order traversal list also between xk-1 and xk.

As an example, here is a non-balanced binary tree without any specific ordering:

     5
   3   6
  9 2   1
       4

The in-order traversal is [9,3,2,5,6,4,1] and the post-order [9,2,3,4,1,6,5].

The tree would be recursively constructed like this: Take last element of post-order traversal (5); divide in-order to [9,3,2] and [6,4,1] (dividing at the location of the element 5); thus the post-order traversal list is split to [9,2,3] and [4,1,6] just based on the now-known sizes of the subtrees. The recursion then continues; let's look at the [6,4,1] tree because it is not balanced:

The root is 6; in the in-order [6,4,1] the left-subtree is empty and the right is [4,1], so from the post-order list [4,1,6] you take [] as the left-subtree and [4,1] as the right subtree; from there you get root-node 1, and you find that [4] is the left subtree; from which you get the shape

  6
   1
  4

as desired.

Now because your tree is not ordered, balanced, etc., you could just try to write recursive code to handle your query. Here it is in C++:

const int size = 7; /* Size of the tree */

/* Given arrays */
int post_order[size] = { 3 , 1 , 2 , 5 , 6 , 7 , 4 };
int in_order[size] = { 3 , 2 , 1 , 4 , 5 , 7 , 6 };

/* Variables updated during recursion */
int min_sum = 99999999; /* not initialized */
int best_leaf = -1; /* not initialized */

/* Recursive descent */
/* prb = post-order range begin, irb = in-order range begin, etc. */
void min_sum_leaf(int acc, int prb, int irb, int len) {
  if (len == 0) return; /* empty subtree */
  if (len == 1) { /* leaf */
    int sum = acc + in_order[irb];
    if (sum<min_sum) { min_sum = sum; best_leaf = in_order[irb]; }
    return;
  }
  /* non-leaf */
  int subtree_root = post_order[prb + len - 1];
  /* find the size of the left subtree */
  int i;
  for (i=0;i<len;i++) {
    if (in_order[irb + i] == subtree_root) break;
  }
  /* Now i is the length of the left subtree, len - i - 1 of the right */
  min_sum_leaf(acc + subtree_root, prb, irb, i);
  min_sum_leaf(acc + subtree_root, prb + i, irb + i + 1, len - i - 1);
}

/* Driver */
int find_min_sum_leaf() {
  min_sum = 99999999; best_leaf = -1;
  min_sum_leaf(0, 0, 0, size);
  return best_leaf;
}

Note: I haven't compiled or run the algorithm but the logic should be there!

antti.huima
Could you please explain me what var aac means, please? I also tried your code and it seems to print the correct ouput except when I have paths that lead to the same sum value, like these 2 sequences: int in_order[size] = {7,8,11,5,5,16,12,18};int post_order[size] = {8,5,11,7,16,18,12,5}; in which there are 3 leafs that lead to sum=31 and, in that case, it gives me a segmentation fault.Perhaps you could help me finding out what causes that segfault.I'm so glad you understood exactly my idea.
neverMind