105 和 106 涉及通过中序遍历结果,配合前序或后序遍历结果来重建原来的二叉树。问题不难,在学习树的遍历的时候,其实应该学会如何解决这种问题。
这类问题的核心思路在于:
- 基于前序,推断出根节点。这是因为前序遍历的过程是,先访问根节点,再访问左子树,最后访问右子树。而后序遍历的过程是先访问左子树,再访问右子树,最后访问根。
- 找到根节点后,再通过中序遍历的结果,找到根在中序遍历中的位置 。那么位置i之前的就是这个根的所有左子树的节点,i之后就是所有右子树的节点。同时也能够确定左右子树的前序遍历结果。
- 递归的重建左右子树
- 把左右子树挂在根上。
代码:
leetcode 105:
class Solution {
public:
TreeNode * build(vector<int> & preorder, vector<int> &inorder, int pl, int pr,int il,int ir)
{
if (pl >= pr)
{
return NULL;
}
if (il >= ir)
{
return NULL;
}
int i;
TreeNode * node=NULL;
for (i = il; i < ir; i++)
{
if (preorder[pl] == inorder[i])
{
node = new TreeNode(preorder[pl]);
//找到了Head
break;
}
}
if (node == NULL) return NULL;
//处理左边
TreeNode * left = build(preorder, inorder, pl + 1, pl + i-il +1 , il, i);
//处理右边
TreeNode * right = build(preorder, inorder, pl + i-il +1,pr,i+1 ,ir );
node->left = left;
node->right = right;
return node;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
return build(preorder, inorder, 0, preorder.size(), 0, inorder.size());
}
};
leetcode 106:
class Solution {
public:
TreeNode * build(vector<int> & inorder, vector<int> &postorder, int il, int ir, int pl, int pr)
{
if (pl > pr) return NULL;
if (il > ir) return NULL;
TreeNode * head = NULL;
int i;
for ( i =il;i<=ir;i++)
{
if (inorder[i] == postorder[pr])
{
head = new TreeNode(inorder[i]);
break;
}
}
if (head == NULL) return NULL;
TreeNode *right = build(inorder,postorder,i+1,ir,pl+i-il,pr-1);
TreeNode *left = build(inorder,postorder,il,i-1,pl,pl+i-il -1);
head->left = left;
head->right = right;
return head;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder)
{
return build(inorder, postorder, 0, inorder.size()-1, 0, postorder.size()-1);
}
};