二叉树_题目2:124. 二叉树中的最大路径和

107 阅读3分钟

题目2:124. 二叉树中的最大路径和

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

同类题目

543. 二叉树的直径

前置知识

题目描述

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

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

给你一个二叉树的根节点 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

思路分析

本题中要求的是二叉树的最大路径和,针对树中的每一个节点,经过该节点的路径有两种。

  • 该节点为子节点,是构成最大路径的一段
  • 该节点为根节点,其左右子树构成最大路径

该节点为子节点,是构成最大路径的一段

该节点为根节点,其左右子树构成最大路径

对每个节点计算左右子树的路径,在计算路径的过程中可以顺便计算最大路径。这样可以把该题分解为求左右子树路径问题,那么计算最大的位置应该是计算出左右子树的最大路径之后,即后序遍历的位置

最大路径值使用一个全局变量进行记录,一个节点的最大路径值有以下几种,要从中选一个最大值记录:

  • cur->val
  • cur->val + left->val
  • cur->val + right->val
  • cur->val + left->val + right->val

当前节点作为根节点时,计算全部;当前节点作为子节点时计算前3个。

剪枝: left->val 或者right->val 为负数时,对于路径最大值是不利的,可以剪掉为负数的子节点。

针对二叉树的题目,可以有3个位置嵌入代码,这三个位置分别是前序位置、中序位置和后序位置。你可以在这3个为置嵌入巧妙的代码逻辑来完成题目的需求。 本题显然是后续位置。

有了这个遍历框架之后,你只需要考虑当前节点应该做什么即可,其它交给框架。

 void traverse(TreeNode root) {
      if (root == null) {
      return;
      }
      // 前序位置
      traverse(root.left);
      // 中序位置
      traverse(root.right);
      // 后序位置
 }

程序代码

 //https://leetcode.cn/problems/binary-tree-maximum-path-sum/description/
 //124. 二叉树中的最大路径和
 #include<iostream>
 using namespace std;
 ​
 ​
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 };
 ​
 ​
 ​
 class Solution {
 private:
     // 记录路径的最大值
     int res = -0x3f3f3f3f;
 public:
 ​
     int getPath(TreeNode* root)
     {
         if(root == NULL)
         {
             return 0;
         }
 ​
         // 负数对于最大路径总和是没有正向用途的,直接剪掉
         int leftv = max(getPath(root->left),0);
         int rightv = max(getPath(root->right),0);
 ​
         // 计算当前节点的路径总和的最大值,下面的一条语句就表达了这4种情况
         // cur->val 
         // cur->val + left->val
         // cur->val + right->val
         // cur->val + left->val + right->val
         int tmpres = root->val + leftv + rightv;
         // 计算全局最大值
         res = max(tmpres, res);
 ​
         // 返回经过该节点的路径时,该节点能贡献的路径最大值,下面的一条语句就表达了这3种情况
         // 1)leftv + root->val
         // 2) rightv + root->val
         // 3) root->val
         // 从上面选择一条路
         int curv = max(leftv ,rightv) + root->val;
         return curv;
 ​
     }   
 ​
     int maxPathSum(TreeNode* root) {
         getPath(root);
         return res;
     }
 };
 ​

题目感悟

  • 最大路径有那几种情况
  • 作为子节点,往上反馈的有哪几种情况

把这两个搞明白,递归的返回值和最大值就确定了,然后就套模板。

更多相关知识:github.com/pingguo1987…