「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。
题目
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 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、停在当前节点
- 2、走该节点的左子树
- 3、走该节点的右子树
对于情况1,说明继续走下去,路径和是减小的,所以选择停在当前节点不动了
对于情况2、3,说明当前节点是默认被添加到了路径上,需要继续往左右子树移动,那么该往哪个子树走,就要看哪个子树能够给路径提供较大的 收益
而每次遇到节点时,都会面临同样的问题,同时二叉树的每个子树又是相同的结构,显然递归算法比较适合解决该问题;
其次,对于一个子树来说,会分为两种情况,一个是其 内部路径
的和就是最大路径和,如例2;另外就是该子树,会成为最大路径和的一部分,如例1的子树 [2]
,称其为 对外最大路径和
;有一个需要注意的问题,某个子树的 对外最大路径和
不能同时包含左右子树,因为在路径上会重复走到该子树的根节点;
定义递归函数 dfs
,返回当前子树 root
的 对外最大路径和
,对应上述三种情况为:
- 1、对外最大路径和为:
root.val
,即路径在此处停下 - 2、对外最大路径和为:
root.val + dfs(root.left)
- 3、对外最大路径和为:
root.val + dfs(root.right)
递归算法代码:
/**
* 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) {
let maxSum = Number.MIN_SAFE_INTEGER;
const dfs = root => {
if(root === null) return 0;
const left = dfs(root.left);
const right = dfs(root.right);
// 内部最大路径和
const innerMaxSum = root.val + left + right;
maxSum = Math.max(maxSum, innerMaxSum);
// 对外最大路径和
const outMaxSum = root.val + Math.max(0, left, right);
return outMaxSum > 0 ? outMaxSum : 0;
}
// 递归开始
dfs(root);
return maxSum;
};
小结
对于具有相同结构的数据,例如二叉树,递归遍历是比较合适的算法;当没有思路的时候,可以尝试在草稿纸上画二叉树的结构,以最简单的开始,如果要寻找一个最大路径和,路径会是怎么样的,在延伸到较为复杂的二叉树,尝试去寻找规律,往往就能得出解题思路
LeetCode 👉 HOT 100 👉 二叉树中的最大路径和 - 困难题 ✅
合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄