leetcode之124二叉树中的最大路径和

题目描述

给定一个非空二叉树,返回其最大路径和。

本题中,路径被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。

示例 1:

输入:[1,2,3]

       1
      / \
     2   3

输出:6

示例 2:

输入:[-10,9,20,null,null,15,7]

   -10
   / \
  9  20
    /  \
   15   7

输出:42

算法

在本题中采用了递归的方法,思路就是遍历每一个结点,然后取得最大值,设结点node,它的左子树的最大值为lNode,它的右子树的最大值为rNode,那么对于结点node的最大路径和为:

max(node.Val,node.Val+lNode,node.Val+rNode,node.Val+lNode+rNode,lNode,rNode),就是获取他们中的最大值

但是我们在求结点node的子树的最大值的时候,需要注意一下几个方面

  • 必须包含子树的根结点的值
  • 必须只能包含子树的一边子树,而不能同时包含左右子树

算法步骤如下:

  • 首先定义递归函数的全局变量res=node.Val
  • 然后定义递归函数,参数就是一个结点node
    • 如果res<node.Val,就将node.Val的结果赋值给res
    • 如果node的左子树存在,调用递归函数,传入node.Left,得到结果lNode
      • 如果res<node.Val+lNode,那么res=node.Val+lNode
      • 如果res<lNode,那么res=lNode
    • 如果node的右子树存在,调用递归函数,传入node.Right,得到结果rNode
      • 如果res<node.Val+rNode,那么res=node.Val+rNode
      • 如果res<rNode,那么res=rNode
    • 当左右子树同时存在的时候,还要比较res<node.Val+lNode+rNode
    • 递归函数的返回值为max(node.Val,node.Val+lNode,node.Val+rNode)

代码

golang

func maxPathSum(root *TreeNode) int {
	if root == nil {
		return 0
	}
	res := root.Val
	var findMax func(node *TreeNode) int
	findMax = func(node *TreeNode) int {
		var lExist, rExist bool
		var Lroot, Rroot int
		tmpMax := node.Val
		if res < node.Val {
			res = node.Val
		}
		if node.Left != nil {
			lExist = true
			Lroot = findMax(node.Left)
			if res < node.Val+Lroot {
				res = node.Val + Lroot
			}
			if res < Lroot {
				res = Lroot
			}
			if tmpMax < node.Val+Lroot {
				tmpMax = node.Val + Lroot
			}
		}
		if node.Right != nil {
			rExist = true
			Rroot = findMax(node.Right)
			if res < node.Val+Rroot {
				res = node.Val + Rroot
			}
			if res < Rroot {
				res = Rroot
			}
			if tmpMax < node.Val+Rroot {
				tmpMax = node.Val + Rroot
			}
		}
		if lExist && rExist {
			// 同时存在左子树和右子树
			if res < node.Val+Lroot+Rroot {
				res = node.Val + Lroot + Rroot
			}
		}
		return tmpMax
	}
	_ = findMax(root)
	return res
}

c++

struct TreeNode{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode():val(0),left(nullptr),right(nullptr){}
    TreeNode(int x):val(x),left(nullptr),right(nullptr){}
    TreeNode(int x,TreeNode *left,TreeNode *right):val(x),left(left),right(right){}
};

class Solution{
    public:
    int maxPathSum(TreeNode *root){
        if (!root){
            return 0;
        }
        int res=root->val;
        findMax(root,res);
        return res;
    }
    int findMax(TreeNode *root,int &res){
        if (!root){
            return 0;
        }
        int tmpMax=root->val;
        res=res>tmpMax?res:tmpMax;
        bool lExist=false,rExist=false;
        int Lroot=0,Rroot=0;
        if (root->left){
            lExist=true;
            Lroot=findMax(root->left,res);
            res=res>root->val+Lroot?res:root->val+Lroot;
            res=res>Lroot?res:Lroot;
            tmpMax=tmpMax>root->val+Lroot?tmpMax:root->val+Lroot;
        }
        if (root->right){
            rExist=true;
            Rroot=findMax(root->right,res);
            res=res>root->val+Rroot?res:root->val+Rroot;
            res=res>Rroot?res:Rroot;
            tmpMax=tmpMax>root->val+Rroot?tmpMax:root->val+Rroot;
        }
        if (lExist&&rExist){
            res=res>root->val+Lroot+Rroot?res:root->val+Lroot+Rroot;
        }
        return tmpMax;
    }
};

int main(){
    //TreeNode *node0=&TreeNode(0);
    //上面这个代码在golang中是可以的,直接使用临时变量的地址初始化指针,但是在c++中就不可以
    TreeNode node1=TreeNode(2);
    TreeNode node2=TreeNode(3);
    TreeNode root=TreeNode(1,&node1,&node2);
    //下面要先定义一个Solution类的实例,采用的是默认初始化的方式
    //不能直接使用Solution::maxPathSum(&root)
    //因为这个函数不是静态成员,所以不能直接通过类名调用,需要通过实例调用
    Solution gyy;
    int res=gyy.maxPathSum(&root);
    cout<<res<<endl;
    return 0;
}
posted @ 2020-12-21 10:45  胖胖咩  阅读(140)  评论(0)    收藏  举报