我有这两个序列用于二叉树(不是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 ......我不介意
答案 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;
}
注意:我没有编译或运行算法,但逻辑应该在那里!