代码随想录 | Day25 | 二叉树:从中序与后序遍历构造二叉树&&最大二叉树

代码随想录 | Day25 | 二叉树:从中序与后序遍历构造二叉树&&最大二叉树

主要学习内容:
用中序和后序来构建二叉树

106.从中序与后序遍历构造二叉树

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

解法思路:

先想想如果没有这个图的话,我们会如何把根据这两个数组把树画出来。

1.中序是左中右,后序是左右中,说明后序数组的末尾肯定是当前还没构造的部分的根结点

2.接下来再根据这个值去中序里面找,找到的话,那它的前面就是左子树,后面就是右子树

3.根据中序数组左子树结点数量,可以确定后序数组中左右的分界,这样就找到了中序和后序数组中,左子树和右子树的范围

4.也就是分别找到了左子树和右子树他们自己的中序和后序数组

5.递归左子树和右子树的中序后序数组,建立左右子树,知道整棵树构建完毕

比如下面,这张图的构造过程

1.先找到根结点3

2.3前面是左子树9,后面是右子树15,20,7

3.左子树大小为1说明,后序数组前面1个数是左子树,到末尾的根结点前是右子树15,7,20

4.左子树中序 :9 后序:9

右子树中序 :15 20 7 后序:15 7 20

5.递归9和9 15 20 7和15 7 20

image-20240927152225450

现在我们了解了大致过程,难点在于

1.我们该如何知道构造完的根结点在哪,即我们的递归函数返回值是什么?

2.递归函数的终止条件又该是什么?

1.我们需要最后返回我们构造的二叉树,所以我们的返回值得是我们构造二叉树的根结点,也是通过函数返回值得到根节点

2.终止条件应该是后序数组为空,后序数组为空说明已经没有结点需要进行构造了、

1.函数参数和返回值

TreeNode *tra(vector<int> i, vector<int> p)

i,p对应当前构造子树的中序和后序数组,返回值TreeNode * 是我们的根结点

2.终止条件

if(p.size()==0) return nullptr;

后序数组为空

3.本层代码逻辑

这部分是最难的地方,我们需要把我们刚刚想象的过程用代码进行复刻、

1.找到当前子树的根结点,就是后序数组的最后一个值

TreeNode *t=new TreeNode(p[p.size()-1]);

2.找到中序数组中左子树和右子树的切分点,即在中序数组中找到根节点,找到根节点的下标位置以后就break

int index=0;
for(index=0;index<i.size();index++)
	if(i[index]==t->val)
		break;

3.构造左子树,要注意采用的区间是左闭右闭还是左闭右开,不管用哪种都要统一

我采用的是左闭右开,因为迭代器的begin和end是左闭右开的

我们切割左子树的中序和后序

中序就是从开始到根结点的下标值,[0,index)

后序也是[0,index)

t->left=tra(
    vector<int>(i.begin(),i.begin()+index),
    vector<int>(p.begin(),p.begin()+index));

4.构造右子树

我们切割右子树的中序和后序

中序就是从开始到根结点的下标值,[index+1,end),end是只想末尾位置的下一位置的迭代器(可以理解为指针),index+1是因为要把根结点跳过,他不属于子树内容

后序是[index,end-1),因为后序的左右子树直接挨着,而最后一个是根节点,我们一样不要根结点

5.返回根结点

return t;

本层逻辑完整代码:

		TreeNode *t=new TreeNode(p[p.size()-1]);
        int index=0;
        for(index=0;index<i.size();index++)
            if(i[index]==t->val)
                break;
        t->left=tra(vector<int>(i.begin(),i.begin()+index),vector<int>(p.begin(),p.begin()+index));
        t->right=tra(vector<int>(i.begin()+index+1,i.end()),vector<int>(p.begin()+index,p.end()-1));
        return t;

完整代码:

class Solution {
public:
    TreeNode *tra(vector<int> i, vector<int> p)
    {
        if(p.size()==0) return nullptr;
        TreeNode *t=new TreeNode(p[p.size()-1]);
        int index=0;
        for(index=0;index<i.size();index++)
            if(i[index]==t->val)
                break;
        t->left=tra(vector<int>(i.begin(),i.begin()+index),vector<int>(p.begin(),p.begin()+index));
        t->right=tra(vector<int>(i.begin()+index+1,i.end()),vector<int>(p.begin()+index,p.end()-1));
        return t;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return tra(inorder,postorder);
    }
};

654.最大二叉树

654. 最大二叉树 - 力扣(LeetCode)

解法:

这没啥好说的,就和上一题一模一样,就是从后序找根节点换成找一个数组里面的最大值了。

class Solution {
public:
    TreeNode *tra(vector<int> nums)
    {
        //终止条件
        if(nums.size()==0)
            return nullptr;
        //记录最大值下标和最大值
        int index=0,maxVal=INT_MIN;
        for(int i=0;i<nums.size();i++)
            if(nums[i]>maxVal)
            {
                maxVal=nums[i];
                index=i;
            }
        //构建根节点
        TreeNode *t=new TreeNode(maxVal);
        //构建左子树,还是采用左闭右开
        t->left=tra(vector<int>(nums.begin(),nums.begin()+index));
        //构建右子树
        t->right=tra(vector<int>(nums.begin()+index+1,nums.end()));
        //返回根节点
        return t;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return tra(nums);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值