方法一(递归)

1.题意整理

  • 给定一颗二叉树,二叉树中每个节点对应一个节点值。
  • 求二叉树中的最大路径和,其中路径指的是从任意节点出发到另一个节点之间所经过的路径。

2.思路整理

对于二叉树的大部分题目,都可以试图分三种情况进行考虑,分别是当前节点的情况、当前节点左子树的情况、当前节点右子树的情况。然后我们给递归的返回值一个含义,即对应节点为根的子树的贡献值。如下图所示,对于叶子节点2和-1,贡献值直接是节点本身,对于非叶子节点1,贡献值为当前节点值加上左右子树贡献值的较大者,如果某个子树贡献值小于0,则看作0来处理。

alt

有了所有子树的贡献值之后,求最大路径和就好办了,只要计算当前节点加上左右子树贡献值,取所有可能中的最大值即可。

  • 递归终止条件:当搜索完所有路径,递归终止,即root为空。
  • 递归如何传递:每次需要往左右子树方向递归,然后利用左右子树的贡献值,可以计算出以当前节点为根的子树中,经过当前节点的所有路径的最大值。
  • 递归的返回值:返回以当前节点为根的子树的贡献值。

图解展示:

alt

3.代码实现

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    //记录最终结果
    int res=Integer.MIN_VALUE;
    public int maxPathSum (TreeNode root) {
        //为空直接返回0
        if(root==null) return 0;
        //递归
        dfs(root);
        return res;
    }
    
    private int dfs(TreeNode root){
        //递归终止条件
        if(root==null) return 0;
        //l表示左子树最大贡献值,r表示右子树最大贡献值,若小于0,则贡献值为0
        int l=Math.max(0,dfs(root.left));
        int r=Math.max(0,dfs(root.right));
        //计算当前节点值,加上左右子树贡献值,取最大的那一个
        res=Math.max(res,root.val+l+r);
        return Math.max(l,r)+root.val;
    }
}

4.复杂度分析

  • 时间复杂度:需要遍历二叉树中所有节点,并且每个节点的访问次数不超过2,所以时间复杂度是O(n)O(n)
  • 空间复杂度:递归栈的深度为log2nlog_2n,当退化为链表时,深度为n,所以空间复杂度为O(n)O(n)