根据一棵树的前序遍历与中序遍历构造二叉树。
注意:
你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
前序遍历首先访问的是根节点,而中序遍历中根节点左、右的数字分别对应左、右子树的节点。
结合上述特征,可先找到根节点,再将问题分解为左、右子树的构造,递归求解。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.empty())
return NULL;
return bTree(preorder, inorder, 0, 0, preorder.size());
}
//递归函数, pi前序遍历中当前对应的起始下标,ii中序遍历中当前对应的起始下标,size当前子树规模
TreeNode* bTree(vector<int>& preorder, vector<int>& inorder, int pi, int ii, int size) {
if (size == 0)
return NULL;
TreeNode* root = new TreeNode(preorder[pi]);//构造当前根节点
int lsize = ii;
while (inorder[lsize] != preorder[pi])//寻找左子树部分
lsize++;
lsize -= ii;//左子树规模
int rsize = size - lsize - 1;//右子树规模
root->left = bTree(preorder, inorder, pi + 1, ii, lsize);
root->right = bTree(preorder, inorder, pi + lsize + 1, ii + lsize + 1, rsize);
return root;
}
};
执行用时 :20 ms, 在所有 C++ 提交中击败了 90.89% 的用户;
内存消耗 :16.7 MB, 在所有 C++ 提交中击败了 45.97% 的用户。
先依次添加左节点,并用栈记录添加的节点,到达当前最大深度后(栈顶 == 中序遍历当前值),回退并添加右子树。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.empty())
return NULL;
stack<TreeNode*> stk;//栈存放添加的节点
TreeNode* root = new TreeNode(preorder[0]);
stk.push(root);
int psize = preorder.size(), isize = inorder.size();
for (int i = 1, j = 0; i < psize && j < isize; i++) {
TreeNode* back = NULL;
TreeNode* node = new TreeNode(preorder[i]);//待添加节点
while (!stk.empty() && stk.top()->val == inorder[j]) {//寻找此时对应的根节点
back = stk.top();//记录当前对应根节点
stk.pop();
j++;
}
if (back == NULL)//为左节点
stk.top()->left = node;
else //为右节点
back->right = node;
stk.push(node);//node成为新的根节点
}
return root;
}
};
执行用时 :12 ms,在所有 C++ 提交中击败了 99.26% 的用户;
内存消耗 :14.4 MB,在所有 C++ 提交中击败了 99.09% 的用户。
暂无。