题目地址:
https://leetcode-cn.com/probl...
题目描述:java
给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不必定通过根节点。 示例 1: 输入: [1,2,3] 1 / \ 2 3 输出: 6 示例 2: 输入: [-10,9,20,null,null,15,7] -10 / \ 9 20 / \ 15 7 输出: 42
解答:
这一题,看上去,根本不可能作出来!为何呢?由于这里的路径和很特别,它能够是从任意点到任意点的路径,搜索我都搜索不出来,按照定义路径能够是从一个叶子到另外一个叶子,好比这样:node
-10 / \ 9 20 / \ 15 7
15->20->7,这条路径,怎么搜索?搜索的代码都写不出来!!!
那么只能放弃了。。。
我认为直接求路径和这题是无解的,写不出代码。而这一题我是求别的东西,顺带求出了答案。算法
可是想一下下面的几个简单问题,这个问题就能作出来了!
(若是跳过这几个简单问题直接看答案,除非你天赋异禀,不然能看懂那你这思惟也是没谁了)函数
二叉树的深度怎么求?code
int depth(TreeNode root) { if(root == null)return 0; return 1+Math.max(depth(root.left),depth(root.right)); }
二叉树的深度等于,max(左子树的深度,右子树的深度)+1。leetcode
假设二叉树的val字段为int类型。
基于求深度的思想,进阶一下求根节点到叶节点的最大路径和:get
int maxSum(TreeNode root) { if(root == null)return 0; return root.val + Math.max(maxSum(root.left),maxSum(root.right)); }
根到叶的最大路径和等于max(左子树根到叶最大路径和,右子树根到叶最大路径和)+root.val。it
如今求,根节点到某一子节点,使得该路径和最大,该子节点能够不是叶子节点,给出最大路径长度。
how?
这个和上面那俩实际上是一个原理,给这个函数起个名字叫作"根向下最大延申"
那么算法是:
int temp =max(左子树根向下最大延申,右子树根向下最大延申)。
若temp > 0,则根向下最大延申=root.val+temp,不然根向下最大延申=root.val
代码为:io
int dfs(TreeNode root) { if(root == null)return 0; int left = dfs(root.left); int right = dfs(root.right); int temp = Math.max(left,right); if(temp > 0) temp += root.val; else temp = root.val; return temp; }
求出上面这个有什么用!!!???用处实在是太大了啊啊啊啊啊!!!!!
求出了上面这个,这个问题就基本可解了!!!
为何呢?
咱们这么想,给我任意一个树的节点root,如今给这个"根向下最大延申"函数起个英文名叫作dfs。那么通过这个节点的最大路径和只多是下面几种状况:
一、
root.val
该节点自己值。
二、
dfs(root.left)+root.val,该节点自己值+左子树向下最大延申。
此时dfs(root.left) > 0 && dfs(root.right) <= 0。
三、
dfs(root.right)+root.val,该节点自己值+右子树向下最大延申。
此时dfs(root.left) <= 0 && dfs(root.right) > 0。
四、dfs(root.left)+dfs(root.right)+root.val
该节点自己值+左右子树向下最大延申。
此时dfs(root.left) > 0 && dfs(root.right) > 0。class
上面四种状况包含了通过这个节点的最大路径和的全部可能。
虽然不能求出任意点到任意点的路径和,可是已经能够获得该题的解了!!!
(读者能够想一想为何不求出任意点到任意点的路径和也能求出答案)
所以,对于任意一个节点root,求出通过该节点的最大路径和,而后和全局答案
进行比较,更新全局答案为最大值,就可以求出这一题的答案!!!
java ac代码:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public int maxPathSum(TreeNode root) { if(root == null)return 0; dfs(root); return ans; } int ans = Integer.MIN_VALUE; //求该点能向下延申的最大值 int dfs(TreeNode root) { if(root == null)return 0; int left = dfs(root.left); int right = dfs(root.right); int temp = Math.max(left,right); if(temp > 0) temp += root.val; else temp = root.val; int val = root.val; if(left >= 0)val += left; if(right >= 0)val += right; ans = Math.max(ans,val); return temp; } }
Amazing!!!
代码如此优美,每一个节点只被访问一次,使得时间效率应该也是最优的,而且还能求出答案,真是Unbelievable!
这题还能这么解!!!这题让求最大路径和,其实是求根节点向下最大延申,而路径和只是顺带着求出来的。
为何不直接给出答案?这是一道hard的题目,若是不写前面的铺垫直接给出答案,多半是看不懂的。