目录
今天周六,早上自然醒,这没什么,只是竟然自然醒的时间比平时闹钟还要早,真是若无闲事挂心头,便是人间好时节,心里没事才是最爽的。
晚上要去建设路和同学吃饭,这是自二月份疫情开始以来第一次外出吃饭,老天保佑。
所以先把每日算法干了。
题目
来源:
给定一个非空二叉树,返回其最大路径和。
本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。
示例 1:
输入: [1,2,3]
1
/ \
2 3
输出: 6
示例 2:
输入: [-10,9,20,null,null,15,7]
-10
/ \
9 20
/ \
15 7
输出: 42
解题思路
-10
/ \
9 20
/ \
15 7
对于一个节点node,其参与一条路径的可能方式有三种:
- node.left, node, node.right;
- node, node.left;
- node, node.right;
1、对于后两种方式,维持一个递归函数maxDown(node)(每次返回node的后两种参与路径方式的最大值,即最大权路径),有这种关系:
maxDown(node) = node.value + Math.max(maxDown(node.left) , maxDown()node.right);
比如:
maxDown(15) = 15 + 0 = 15;(没得子节点)
maxDown(7) = 7 + 0 = 7;(没得子节点)
maxDown(20) = 20 + max(15, 7) = 35;
2、对于第一种方式,遍历到每个节点的时候,计算一下这种三个节点都包含进去的路径是否长于上一轮保存的最长路径和,如果大的话,就更新最长路径和。
设置变量 - 最长路径和(动态更新的变量)
int maxSum = Integer.MIN_VALUE;
遍历到node:
curTreMax = node.value + Math.max( maxDown(node.left), 0)(>0才有意义) + Math.max( maxDown(node.right), 0);
如果curTreMax > maxSum ,就更新maxSum = curTreMax ;
递归返回当前节点的最长路径和(并不针对全局的maxSum,只是针对当前node,即maxDown(node)):
maxDown(node) = node.value + Math.max(leftMax, rightMax);
其中;
int leftMax = Math.max( maxDown(node.left), 0); // 左子树
int rightMax = Math.max( maxDown(node.right), 0); // 右子树
代码
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int maxSum = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxDown(root);
return maxSum;
}
public int maxDown(TreeNode node){
if(node == null) return 0;
int leftMax = Math.max(maxDown(node.left), 0);
int rightMax = Math.max(maxDown(node.right), 0);
int curTreMax = node.val + leftMax + rightMax;
maxSum = Math.max(curTreMax, maxSum);
return node.val + Math.max(leftMax, rightMax);
}
}
复杂度分析
时间复杂度:O(N) 其中 N是结点个数。我们对每个节点访问不超过 2 次。
空间复杂度:O(log(N))。我们需要一个大小与树的高度相等的栈开销,对于二叉树空间开销是 O(log(N))。