Java / C / C ++:在不重构树的情况下找到二叉树最短路径的叶子(帮助递归)

时间:2010-02-12 17:38:30

标签: java c algorithm recursion

我有这两个序列用于二叉树(不是BSD):
InOrder:3 2 1 4 5 7 6
PostOrder:3 1 2 5 6 7 4

我们知道postOrder中的最后一个元素是根,所以我们在inOrder序列中找到根,并按照以下方式细分:
- 根左侧的所有元素都转到左子树 - 根右侧的所有元素都转到右侧子树 而且,它们出现在树中的顺序由postOrder给出。

对于这个例子: 4 = root

左子树(有序):3 2 1右子树(有序):5 7 6
左子树(后序):3 1 2 右子树(后序):5 6 7

我们也这样做,递归...所以,我认为重建的树是:

              4
         2         7
      3     1    5   6

我想只返回通向最短路径的叶子(总和);我不需要重建树然后遍历它并做一条最短的路径。我只需要把叶子带到最小的总和。 在这种情况下,我有4条可能的路径:4 + 2 + 3 = 9 || 4 + 2 + 1 = 7 || 4 + 7 + 5 = 16 || 4 + 7 + 6 = 17,因为少数是7,我必须返回叶子1。

我认为算法非常简单,但我很难为它编写递归代码......

有人可以帮助一个菜鸟吗? C,Java,C ++或Python ......我不介意

1 个答案:

答案 0 :(得分:1)

如果您对一般二叉树进行了有序遍历和后序遍历,则如果您可以具有重复值,则它们甚至不能唯一地定义树。后序和有序的序列[1,1,1]可以是以下树之一:

    1      1
   1 1      1
             1

最小和路径左边的总和为2,右边的总和为3。

因此假设所有值都是不同的。

假设您有一个后期遍历列表[x1,x2,...,xn]和有序遍历列表[y1,...,yk,...,yn],以便xn == yk 。因为xn是树的根,所以现在知道[y1,...,yk-1]是左子树,而[yk + 1,...,yn]是正确的子树。左子树也由[x1,...,xk-1]表示,因为左子树的大小显然是常数,所以你也可以在xk-1和xk之间划分后序遍历列表。

例如,这是一个没有任何特定排序的非平衡二叉树:

     5
   3   6
  9 2   1
       4

有序遍历为[9,3,2,5,6,4,1]和后序[9,2,3,4,1,6,5]。

树将以这样的方式递归构造:获取后序遍历的最后一个元素(5);按顺序划分为[9,3,2]和[6,4,1](除以元素5的位置);因此,后序遍历列表仅根据现在已知的子树大小分为[9,2,3]和[4,1,6]。递归然后继续;让我们看看[6,4,1]树,因为它不平衡:

根是6;在有序[6,4,1]中,左子树是空的,右边是[4,1],所以从后序列表中[4,1,6]你把[]作为左 - 子树和[4,1]作为右子树;从那里你得到根节点1,你发现[4]是左子树;从中获得形状

  6
   1
  4

根据需要。

现在因为你的树没有排序,平衡等等,你可以尝试编写递归代码来处理你的查询。这是在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;
}

注意:我没有编译或运行算法,但逻辑应该在那里!