【笔试训练】给一个数组构建二叉树|从前序遍历与中序遍历构建二叉树|二叉树中的最大路径和

文章目录


1.给一个数组构建二叉树

思路:就是借助一个队列实现层序遍历的思想。

先将root节点入队列,构造左右节点后,root取出来时,将其左右孩子都入队列。

cpp 复制代码
struct TreeNode
{
	unique_ptr<TreeNode> left;
	unique_ptr<TreeNode> right;
	int _val;

	TreeNode(int val)
		:_val(val)
		,left(nullptr)
		,right(nullptr)
	{}

	~TreeNode()
	{}
};

//层序遍历构建二叉树
// 1 2 3 4 5
unique_ptr<TreeNode> BuildBinaryTreeFromLevelOrder(vector<int>& nums)
{
	if (nums.size() == 0)
	{
		cout << "nums is empty!" << endl;
	}

	unique_ptr<TreeNode> root = make_unique<TreeNode>(nums[0]);
	queue<TreeNode*> q;
	q.push(root.get());
	int i = 1;
	while (!q.empty() && i < nums.size())
	{
		TreeNode* cur = q.front();
		q.pop();
		//先处理左子树
		cur->left = make_unique<TreeNode>(nums[i]);
		q.push(cur->left.get());
		
		i++;
		//再处理右子树
		if (i < nums.size())
		{
			cur->right = make_unique<TreeNode>(nums[i]);
			q.push(cur->right.get());
		}
		i++;
	}
	return root;
}

2.从前序遍历和中序遍历构建二叉树

从前序遍历和中序遍历构建二叉树

思路:

  • 1.根据前序遍历的根,先找到中序遍历的根节点所在下标。
  • 2.然后划分成两个区间进行递归即可。

注意事项:

previ是前序中的根节点下表,用来构建当前节点的。

所以构建完根节点后, 需要++previ,到达左子树的根节点。

并且要传引用。否则回到当前递归栈这一层时,会从原位置开始向下走

cpp 复制代码
class Solution {
public:
    TreeNode* _buildTree(vector<int>& preorder,vector<int>& inorder,
                        int& previ,int inbegin,int inend)
    {
        if(inbegin > inend)
            return nullptr; //子区间递归结束了
        
        TreeNode* root = new TreeNode(preorder[previ]);
        //1.先在中序区间找根节点下标
        int rooti = 0;
        while(rooti <= inend)
        {
            if(preorder[previ] == inorder[rooti])
                break;
            ++rooti;
        }

        //2.分成左右子区间分别构建子树。
        ++previ; //根节点的下一个节点就是左子树的根了
        root->left = _buildTree(preorder,inorder,previ,inbegin,rooti-1);
        //这里不要再++prei,因为递归构建左子树时,会自己++prei,构建左子树的最后
        //一个节点时,会先++prei,就到右子树了。
        root->right = _buildTree(preorder,inorder,previ,rooti+1,inend);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        //根据前序遍历的根,先找到中序遍历的根节点所在下标。
        //然后划分成两个区间进行递归即可。
        int previ = 0; //传参时一定是传引用,否则回到当前递归栈这一层时
                       //会从原位置开始向下走
        int inbegin = 0,inend = inorder.size()-1;
        return _buildTree(preorder,inorder,previ,inbegin,inend);
    }
};

3.二叉树中的最大路径和

二叉树中的最大路径和

思路:二叉树中一条路的最大路径和一定是该节点的左子树的最大有效值与右子树的最大有效值的最大值的和,再加上当前节点的值。

所以:

  • 1.先求出左右子树的最大有效值,再加上当前节点的值。
  • 2.求有效值的过程,不断更新最大路径和。

这里注意两个概念:

  • 1.最大贡献值是因为左子树可能有几十条路径,需要选出最优的路径,才是最大的贡献。
    左右子树的最大贡献值加起来,再加上我当前节点的值之后,才组成最大路径和(左右都是最优的路径)。我的左子树和右子树两条路径选出来,比较后,选最大的,再加上我当前节点的值,然后向上交付,就能组成一条最优的路径。
  • 2.最大路径和就是:左右子树的最大贡献值,加上我当前节点的值,就组成了一条完整的路径。

别看这道题是困难题,如果想明白了后序遍历,就一点不难。

cpp 复制代码
class Solution {
    int max_val = INT_MIN; //保存最大的路径和
public:
    int _paxPathSum(TreeNode* root)
    {
        if(root == nullptr)
            return 0; //空节点的有效值为0
        
        //保存左右子树的最大贡献值
        int left_con = max(_paxPathSum(root->left),0);
        int right_con = max(_paxPathSum(root->right),0);

        //更新最大路径和
        max_val = max(max_val,left_con + right_con + root->val);
        //返回贡献值
        return root->val + max(left_con,right_con);
    }
    int maxPathSum(TreeNode* root) 
    {
        _paxPathSum(root);

        return max_val;
    }
};
相关推荐
星沁城1 天前
236. 二叉树的最近公共祖先
java·数据结构·leetcode·二叉树
mikey棒棒棒2 天前
二叉树的遍历与构造
算法·二叉树
好易学·数据结构3 天前
可视化图解算法36: 序列化二叉树-I(二叉树序列化与反序列化)
数据结构·算法·leetcode·二叉树·力扣·序列化·牛客
海码0079 天前
【Hot 100】94. 二叉树的中序遍历
数据结构·c++·算法·二叉树·hot100
想不明白的过度思考者15 天前
初识数据结构——二叉树从基础概念到实践应用
数据结构·二叉树
好易学·数据结构18 天前
可视化图解算法:二叉树的最大深度(高度)
数据结构·算法·二叉树·最大高度·最大深度·二叉树高度·二叉树深度
好易学数据结构20 天前
可视化图解算法:按之字形顺序打印二叉树( Z字形、锯齿形遍历)
数据结构·算法·leetcode·面试·二叉树·力扣·笔试·遍历·二叉树遍历·牛客网·层序遍历·z·z字形遍历·锯齿形遍历
carpell1 个月前
二叉树实战篇2
python·二叉树·数据结构与算法
David Bates1 个月前
代码随想录第18天:二叉树
python·算法·二叉树