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

文章目录


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;
    }
};
相关推荐
想睡hhh2 天前
Practice 2025.6.1—— 二叉树进阶面试题(2)
c++·算法·二叉树·遍历
June`4 天前
深度刨析树结构(从入门到入土讲解AVL树及红黑树的奥秘)
数据结构·c++·二叉树·红黑树·二叉搜索树··avl树
旺仔老馒头.7 天前
【数据结构】树形结构--二叉树
c语言·数据结构·二叉树·深度优先
丶Darling.10 天前
Day126 | 灵神 | 二叉树 | 层数最深的叶子结点的和
数据结构·c++·算法·二叉树·深度优先
白白糖11 天前
相同,对称,平衡,右视图(二叉树)
python·算法·二叉树·力扣
丶Darling.11 天前
Day125 | 灵神 | 二叉树 | 二叉树中的第K大层和
数据结构·c++·学习·算法·二叉树
丶Darling.17 天前
Day119 | 灵神 | 二叉树 | 二叉树的最近共公共祖先
数据结构·c++·算法·二叉树
方博士AI机器人19 天前
算法与数据结构 - 二叉树结构入门
数据结构·算法·二叉树
袁气满满~_~19 天前
LeetCode:617、合并二叉树
算法·leetcode·二叉树