[前端]_一起刷leetcode 124. 二叉树中的最大路径和

780 阅读3分钟

大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。

题目

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

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

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

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

 

示例 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

 

提示:

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

思路

求最大路径和: 可以转换成递归的问题, 首先最大路径和要么存在根节点,要么存在根节点的左子树,也就是左节点,要么存在左子树,也就是右节点,只有这三种情况,我们层层递归转换下去即可。但是由于要求路径和,所以我们得先求出每个节点的最长路径,用map也就是前缀和来记录,然后才能通过第二次遍历去递归的找到最大路径和。

  1. 先找到各个节点的最大路径和,取左右节点和的最大值加上当前节点的值;
  2. 再次遍历树,对比每个节点的三种情况:取左边,取右边,或者取中间;
  3. 形成一个递归问题,递归的转移方程是把求解当前节点的最大值分成了三个部分做比较。

实现

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxPathSum = function(root) {
    if (!root) return 0;
    let map = getPathMap(root);

    function getPathSum(node) {
        if (!node) return 0;

        let leftValue = Math.max((map.get(node.left) || 0), 0);
        let rightValue = Math.max((map.get(node.right) || 0), 0);

        // 当前节点的最大值,等于左右两个节点的最大值和加当前值
        let cur = node.val + leftValue + rightValue;

        let compareList = [ cur ];
        node.left && compareList.push(getPathSum(node.left));
        node.right && compareList.push(getPathSum(node.right));

        return Math.max(...compareList);
    }

    return getPathSum(root, map);
};

// 找到每个节点的路径前缀和
function getPathMap(root) {
    let map = new Map();

    // 找到每个节点的最大单边路径,
    const getMaxPath = (node) => {
        if (!node) return 0;

        const maxSubValue = Math.max(getMaxPath(node.left), getMaxPath(node.right));
        const maxValue = maxSubValue > 0 ? node.val + maxSubValue : node.val;
        map.set(node, maxValue);

        return maxValue;
    }

    getMaxPath(root);

    return map;
}   

优化

  1. 我们发现自上而下的递归,需要用map保存一遍值,同时走两轮递归才能找到相应的结果;
  2. 但是自下而上的递归则不用,可以获取最长路径的同时直接在外部记录最大值即可。

优化代码

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxPathSum = function(root) {
    if (!root) return 0;

    let maxValue = Number.MIN_SAFE_INTEGER;

    // 找到每个节点的最大单边路径
    const getMaxPath = (node) => {
        if (!node) return 0;

        // 后序遍历,先找子节点
        // 如果节点路径是负的我们就不加,当作没有这个节点
        const leftValue = Math.max(getMaxPath(node.left), 0);
        const rightValue = Math.max(getMaxPath(node.right), 0);

        // 把总路径和最大值记录下来
        maxValue = Math.max(maxValue, node.val + leftValue + rightValue);

        return Math.max(leftValue, rightValue) + node.val;
    }

    getMaxPath(root);

    return maxValue;
};

 

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。