Construct Binary Tree from Inorder and Postorder Traversal
原题目连接地址:https://oj.leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/
Runtime:
194 ms
一、实例
后序遍历 DGJHEBIFCA 中序遍历 DBGEHJACIF 请构造二叉树。
二、分析
1、根据后序遍历的特点,'A' 为树第一层根节点,那么由中序遍历即可得 ‘DBGEHJ’ 和 ‘CIF’ 分别为左右子树;
2、继续往前扫描后序遍历序列,'C' 为 'A' 右子树根节点,即第二层根节点,‘NULL’ 和 'IF' 分别为 'C' 的左右子树;
3、继续往前扫描后序遍历序列,'F' 为 'C' 右子树根节点,即第三层根节点,'I' 和 'NULL' 分别为 'F' 的左右子树;
4、继续往前扫描后序遍历序列,'I' 为 'F' 左子树根节点,即第四层根节点,'NULL' 和 'NULL' 分别为 'I' 的左右子树;
5、继续往前扫描后序遍历序列,'B' 为 ‘A’ 左子树根节点,即第二层根节点,以此类推得到完整左子树,结果如图。
三、总结
1、树以递归实现比较清晰易懂简短,但是消耗空间,一般情况下oj平台难以通过。实现思路如下,
递归步,以根节点为中心,建立第一层根节点,先构建其右子树,再构建其左子树;再以右子树根节点为中心,递归调用构建右、左子树;直到构建完整树。
递归基,如果子树为空,则返回NULL(表示不建立节点);如果子树有一个值,则构建叶节点。
2、将递归代码转成非递归代码,需要用到栈。实现思路如下,
递归步,以根节点为中心,构建第一层根节点,声明定义左子树、右子树,压入栈,同时需要将中序遍历序列中左右子树部分的头尾序号压入栈中;再取出子树,以 其为中心,构建右、左子树,同时将左右子树序号压入栈中;直到构建完整树;
递归基,如果子树为空,则返回NULL(表示不建立节点);如果子树有一个值,则构建叶节点。
此外,还需要加入边界值的判断,如空树、只有根节点的树;其次如果子树为空,需要将已经声明定义好的左右子树delete。
四、实现方案
递归实现方案:
<pre name="code" class="cpp">#include<vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
if (inorder.size() == 0){
return NULL;
}
if (inorder.size() == 1)
{
struct TreeNode *tree = new TreeNode(inorder[0]);
return tree;
}
int i;
for (i = 0; i < inorder.size(); i++)
{
if (inorder[i] == postorder.back())
break;
}
vector<int> postorderCopy = postorder;
int rootNode = postorderCopy.back();
postorderCopy.pop_back();
struct TreeNode *tree = new TreeNode(rootNode);
vector<int> inorderLeft, inorderRight;
if (0 <= i - 1)
{
//inorderLeft.assign(inorder.begin(), inorder.begin() + i - 1);
for (int j = 0; j < i; j++)
inorderLeft.push_back(inorder[j]);
}
tree->left = buildTree(inorderLeft, postorderCopy);
if (i + 1 <= inorder.size() - 1)
{
//inorderRight.assign(inorder.begin() + i + 1, inorder.end());
for (int j = i + 1; j < inorder.size(); j++)
inorderRight.push_back(inorder[j]);
}
tree->right = buildTree(inorderRight, postorderCopy);
return tree;
}
};
void preorder_travel(TreeNode *tree)
{
if (tree == NULL)
{
cout << "# ";
return;
}
cout << tree->val << " ";
preorder_travel(tree->left);
preorder_travel(tree->right);
}
int main(int argc, char **argv[])
{
vector<int> io = { 2, 3, 1 };
vector<int> po = { 3, 2, 1 };
Solution s;
preorder_travel(s.buildTree(io, po));
cout << endl;
return 0;
}
</pre><pre>
非递归的实现方案:
<pre name="code" class="cpp">class Solution {
public:
bool deleteNode(TreeNode *root, TreeNode *tree)
{
if (root != NULL)
{
if (root->right == tree)
{
delete tree;
root->right = NULL;
return true;
}
if (root->left == tree)
{
delete tree;
root->left = NULL;
return true;
}
deleteNode(root->right, tree);
deleteNode(root->left, tree);
return false;
}
}
TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) {
if (inorder.size() != postorder.size())
return NULL;
if (inorder.size() == 0 && postorder.size() == 0)
return NULL;
if (inorder.size() == 1 && postorder.size() == 1)
{
TreeNode *tree = new TreeNode(inorder[0]);
return tree;
}
vector <int> stack;
TreeNode *tree = new TreeNode(0);
vector <TreeNode *> treeStack;
treeStack.push_back(tree);
stack.push_back(0);
stack.push_back(postorder.size() - 1);
while (treeStack.size() > 0)
{
int right = stack.back(); stack.pop_back();
int left = stack.back(); stack.pop_back();
TreeNode *tree2 = treeStack.back();
treeStack.pop_back();
if (left > right)
{
deleteNode(tree, tree2);
continue;
}
if (left == right)
{
tree2->val = postorder.back();
postorder.pop_back();
continue;
}
int i;
for (i = 0; i < inorder.size(); i++)
{
if (inorder[i] == postorder.back())
break;
}
tree2->val = postorder.back();
postorder.pop_back();
TreeNode *treeLeft = new TreeNode(0);
tree2->left = treeLeft;
treeStack.push_back(treeLeft);
stack.push_back(left);
stack.push_back(i - 1);
TreeNode * treeRight = new TreeNode(0);
tree2->right = treeRight;
treeStack.push_back(treeRight);
stack.push_back(i + 1);
stack.push_back(right);
}
return tree;
}
};