【JS每日一算法】🟥118.二叉树中的最大路径和(动态规划)

363 阅读3分钟

二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

提示:

  • 树中节点数目范围是 [1, 3 * 104]
  • -1000 <= Node.val <= 1000

例 1:

输入: root = [1,2,3]
输出: 6
解释: 最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例 2:

输入: root = [-10,9,20,null,null,15,7]
输出: 42
解释: 最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

题解:

个人博客

更多JS版本题解点击链接关注该仓库👀

/**
 * @description: 递归回溯  TC:O(n)  SC:O(n)
 * @author: JunLiangWang
 * @param {*} root 给定树的根节点
 * @return {*}
 */
function recursionBacktracking(root) {
    /**
     * 该方案使用递归回溯的方式,试想对于如下的一棵树:
     *            x1
     *          /   \
     *        x2     x3
     *        /\     /\
     *      x4  x5 x6  x7
     * 
     * 对于其子树而言:
     *         ...
     *         /
     *        x2    
     *        /\    
     *      x4  x5
     * 
     * 它只有三种方式通向其他路径:   对应得路径和为:
     *    1. x2-->其他节点             1.x2.val+other
     *    2. x4-->x2-->其他节点        2.x4.val+x2.val+other
     *    3. x5-->x2-->其他节点        3.x5.val+x2.val+other
     * 
     * 该子树通往其他节点的最大路径和就为:
     *    toOtherMaxSum=Max(x2.val , x4.val+x2.val , x5.val+x2.val )
     * 也就是:
     *    toOtherMaxSum=Max(root.val , left.val+root.val , right.val+root.val )
     * 
     * 由于我们并不知道其他节点的值,万一其他节点值全是负数,那么
     * 路径和最大值就在该子树内,因此我们还需要定义一个变量,计算
     * 该子树内的路径最大和,不断根据该子树内的路径最大和更新最大
     * 值
     *  maxSum=Max(maxSum,通往其他路径的最大和, x4.val , x5.val , x4.val+x5.val+x2.val )
     * 也就是:
     *  maxSum=Max(maxSum,toOtherMaxSum, left.val , right.val , left.val+right.val+root.val )
     * 
     * 最终我们利用上述方法,以递归回溯的方式不断遍历子树即可
     * 
     */

    // 记录最大路径和,初值为根的值
    let maxSum = root.val;

    /**
     * @description: 递归回溯遍历树
     * @author: JunLiangWang
     * @param {*} root 当前子树根节点
     * @return {*}
     */    
    function recursion(root) {
        // 无子树,返回路径和为最小值,因为给定题目中
        // 节点最小值为-1000,为了不影响后续比较结果
        // 因此这里返回最小值
        if (!root) return -1001;
        // 继续递归左子树
        let leftSum = recursion(root.left),
        // 继续递归右子树
        rightSum = recursion(root.right),

        /* 对于一棵子树它只有三种方式通向其他路径:     对应得路径和为:
        *    1. 根节点(x2)-->其他节点                    1.x2.val+other
        *    2. 左节点(x4)-->根节点(x2)-->其他节点       2.x4.val+x2.val+other
        *    3. 右节点(x5)-->根节点(x2)-->其他节点       3.x5.val+x2.val+other
        * 
        * 该子树通往其他节点的最大路径和就为:
        *   toOtherMaxSum=Max(root.val , left.val+root.val , right.val+root.val )
        * */
        toOtherMaxSum = Math.max(leftSum + root.val, rightSum + root.val, root.val)

        /* 由于我们并不知道其他节点的值,万一其他节点值全是负数,那么路径和最大值就
        *  在该子树内,因此我们还需要定义一个变量,计算该子树内的路径最大和,不断根
        *  据该子树内的路径最大和更新最大值:
        *    maxSum=Max(maxSum,toOtherMaxSum, left.val , right.val , left.val+right.val+root.val )
        * */
        maxSum = Math.max(maxSum, toOtherMaxSum, leftSum + root.val + rightSum, leftSum, rightSum)
        // 该子树通往其他节点的最大路径和
        return toOtherMaxSum
    }
    // 执行递归
    recursion(root)
    // 返回最大值
    return maxSum
}