二叉树通过前序和中序(中序和后序)构造二叉树总结

以中序遍历数组和后序遍历数组为例:

class Solution {
   public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        // 第一步:判断特殊情况
        if (inorder.size() == 0 || postorder.size() == 0) {
            return nullptr;
        }

        // 第二步:确定根节点(后序数组中的最后一个节点)
        int rootVal = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootVal);

        // 如果后序数组中就一个元素,直接返回
        if (postorder.size() == 1) {
            return root;
        }

        // 第三步:以根节点的值定位切割点
        //找中序数组的切割位置
        int delimiterIndex;
        for(delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++){
            if(inorder[delimiterIndex] == rootVal){
                break;
            }
        }
        
        // 第四步:以切割点分割中序数组
        //采用左闭右开原则
        vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);//左区间:[0,delimiterIndex)
        vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());//右区间:[delimiterIndex + 1,end)
        
        // 第五步:切割后序数组
        //根据中序数组切割后的结果左右区间的大小来分割后序数组
        postorder.resize(inorder.size() - 1);

        // 左闭右开,注意这里使用了左中序数组大小作为切割点
        vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());//[0, leftInorder.size)
        vector<int> rightPostorder(postorder.begin() + leftInorder.size(),postorder.end());// [leftInorder.size(), end)

        // 第六步:递归处理左区间和右区间
        root->left = buildTree(leftInorder, leftPostorder);
        root->right = buildTree(rightInorder, rightPostorder);

        return root;
    }
};

第一步:经典判断特殊情况

如果后序数组或者前序数组为空的话,直接返回nullptr就好了。

if (inorder.size() == 0 || postorder.size() == 0) {
            return nullptr;
}

第二步:确定根节点

后序数组中的最后一个节点 or 前序数组的第一个节点

int rootVal = postorder[postorder.size() - 1];
//int rootVal = preorder[0];
TreeNode* root = new TreeNode(rootVal);

生成节点之后,再进行一步判断,就是后序/前序数组大小是否为1,如果是1的话就直接返回根节点就行了。

if (postorder.size() == 1) {
	return root;
}

第三步:以根节点的值定位切割点

定位根节点的下标:在中序数组中遍历查询

//找中序数组的切割位置
int delimiterIndex;
for(delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++){
	if(inorder[delimiterIndex] == rootVal){
		break;
	}
}

第四步:以切割点分割中序数组

首先需要确认切割数组的原则,本题采用的是左闭右开的原则

//采用左闭右开原则
vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);//左区间:[0,delimiterIndex)
vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end());//右区间:[delimiterIndex + 1,end)

第五步:切割后序数组

后序数组第一个元素已经用过了,需要去掉

postorder.resize(inorder.size() - 1);

如果是前序数组的话,就是去除第一个元素

preorder.erase(preorder.begin());

根据中序数组切割后的结果左右区间的大小来分割后序数组

vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());//[0, leftInorder.size)
vector<int> rightPostorder(postorder.begin() + leftInorder.size(),postorder.end());// [leftInorder.size(), end)

第六步:递归处理左区间和右区间

root->left = buildTree(leftInorder, leftPostorder);
root->right = buildTree(rightInorder, rightPostorder);

总结:通过两个数组构造二叉树只有两种方式:前序数组和中序数组,后序数组和中序数组,通过上述的解法,可以很好的解决构造二叉树的问题,本题采用递归的解法,还有迭代法的解法,有兴趣的可以进一步学习一下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值