在接受采访时遇到了这个问题。 给定遍历二叉树的顺序。从中打印所有可能的二叉树。
初步想法:
如果说我们阵列中只有2个元素。说2,1。 然后是两棵可能的树
2
\
1
1
/
2
如果3个元素说,2,1,4。然后我们有5棵树。
2 1 4 2 4
\ / \ / \ /
1 2 4 1 4 2
\ / / \
4 2 1 1
所以,基本上如果我们有n个元素,那么我们有n-1个分支(childs,/或)。 我们可以按任何顺序安排这些n-1个分支。 对于n = 3,n-1 = 2.因此,我们有2个分支。 我们可以通过以下方式安排2个分支:
/ \ \ / /\
/ \ / \
初步尝试:
struct node *findTree(int *A,int l,int h)
{
node *root = NULL;
if(h < l)
return NULL;
for(int i=l;i<h;i++)
{
root = newNode(A[i]);
root->left = findTree(A,l,i-1);
root->right = findTree(A,i+1,h);
printTree(root);
cout<<endl;
}
}
答案 0 :(得分:4)
这个问题很好地分解为子问题。给定一个inorder遍历,在选择一个根之后,我们知道之前的所有内容都是左子树,而后面是正确的子树(可能是空的)。
因此,为了枚举所有可能的树,我们只是尝试所有可能的根值,并递归求解左和下;正确的子树(虽然这些树的数量增长很快!)
antonakos提供了显示如何执行此操作的代码,尽管该解决方案可能会使用比预期更多的内存。这可以通过在递归中添加更多状态来解决,因此它不必保存左侧和右侧的答案列表。对,并在最后结合它们;而是嵌套这些进程,并在找到它们时打印每个树。
答案 1 :(得分:1)
我会编写一个用于构建树的函数,另一个用于打印它们。
树木的建造是这样的:
#include <vector>
#include <iostream>
#include <boost/foreach.hpp>
struct Tree {
int value;
Tree* left;
Tree* right;
Tree(int value, Tree* left, Tree* right) :
value(value), left(left), right(right) {}
};
typedef std::vector<Tree*> Seq;
Seq all_trees(const std::vector<int>& xs, int from, int to)
{
Seq result;
if (from >= to) result.push_back(0);
else {
for (int i = from; i < to; i++) {
const Seq left = all_trees(xs, from, i);
const Seq right = all_trees(xs, i + 1, to);
BOOST_FOREACH(Tree* tl, left) {
BOOST_FOREACH(Tree* tr, right) {
result.push_back(new Tree(xs[i], tl, tr));
}
}
}
}
return result;
}
Seq all_trees(const std::vector<int>& xs)
{
return all_trees(xs, 0, (int)xs.size());
}
观察到对于根值,有多个树可以从根值的左侧和右侧的值构造。包括这些左右树的所有组合。
编写漂亮的打印机是一个练习(一个无聊的),但我们可以测试该函数确实构建了预期的树数:
int main()
{
const std::vector<int> xs(3, 0); // 3 values gives 5 trees.
const Seq result = all_trees(xs);
std::cout << "Number of trees: " << result.size() << "\n";
}