首页 > 试题广场 >

给定一棵二叉树,求各个路径的最大和。

[问答题]
给定一棵二叉树,求各个路径的最大和,路径可以以任意节点作为起点和终点。
比如给定以下二叉树:
  2
 /  \
5    3
返回10。
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
int maxPathSum(TreeNode *root)

最大和只有三条路径。
1.左边某点到根结点。
2.右边某点到根结点。
3.左边某点到根结点再到右边某点。
递归遍历,用一个全局的变量记录最大值。
代码如下:
// 获得包含该结点的最大和
int help(TreeNode *root, int &m) {
    if(root == 0) return 0;
    int l = help(root->left, m); // 获得该结点左子树最大和
    int r = help(root->right, m);// 获得该结点右子树最大和
    // 取左右子树和中较大的那个,如果都小于0,则左右子树都舍弃
    int ret = max(max(l, r), 0) + root->val; 
    // 列举三种结果并与最大值做比较
    m = max(m, max(ret, l + r + root->val));
    return ret;
}
intmaxPathSum(TreeNode *root) {
  int max = root->val;
  // help中max参数为引用,可视为全局变量
  help(root, max);
  return max;
}

编辑于 2016-04-14 20:13:56 回复(1)
//思路:二叉树递归套路题,但此题的难点在于分析可能性,即最大路径和可能出现的情形
//将二叉树分为三个大块,头结点,左子树,右子树,最大路径和无外乎出现在三大块中或者它们的结合
//情况如下:1、左子树
//         2、右子树
//         3、头结点(左右子树上都位负结点)
//         4、左子树+头结点(头结点+必须以左子树头结点开头的最大路径和)
//         5、右子树+头结点
//         6、左子树+头结点+右子树        最大路径和一定在这6种情况中
//分析需要统计的信息,对于1,2 统计左子树(右子树)最大路径和
//对于4,5,6 需要统计必须以头结点开头的最大路径和
#include <iostream>
using namespace std;
inline int max(int a, int b)
{
    return a > b ? a : b;
}
class Node
{
public:
    Node* left = nullptr;
    Node* right = nullptr;
    int val = 0;
    Node(int v):val(v){}
};

class ReturnType
{
public:
    int maxPathSum = 0;
    int headFirstMaxPathSum = 0;
    ReturnType(int m,int h):maxPathSum(m),headFirstMaxPathSum(h){}
};

ReturnType process(Node* head)
{
    if (head == nullptr)return ReturnType(INT_MIN, INT_MIN);
    ReturnType left = process(head->left);
    ReturnType right = process(head->right);
    int p1 = left.maxPathSum;
    int p2 = right.maxPathSum;
    int p3 = head->val;
    
    int p4 = head->val;
    if (left.maxPathSum != INT_MIN)
        p4 += left.headFirstMaxPathSum;
    int p5 = head->val;
    if (right.maxPathSum != INT_MIN)
        p5 += right.headFirstMaxPathSum;
    int p6 = head->val;
    if (left.maxPathSum != INT_MIN && right.maxPathSum != INT_MIN)
        p6 += left.headFirstMaxPathSum + right.headFirstMaxPathSum;
    int maxPathSum = max(max(max(p1, p2), max(p3, p4)), max(p5, p6));
    int headFirstPathSum = max(p3, max(p4, p5));
    return ReturnType(maxPathSum, headFirstPathSum);
}
int getMaxPathSum(Node* root)
{
    return process(root).maxPathSum;
}
发表于 2020-04-15 13:52:46 回复(0)

#include<iostream>
#include<limits.h>
using namespace std;

//节点形式
struct Node
{
    int val;
    Node* left;
    Node* right;
    Node(int x) :val(x), left(nullptr), right(nullptr)
    {}
};
//
//给定三个数求最大值
int GetMax1(int a, int b, int c)
{
    int max = a > b ? a : b;
    max = max > c ? max : c;
    return max;
}

int maxVal1 = INT_MIN;
int maxSum(Node *root)
{
    if (root == NULL)
        return 0;

    /*求以root为根的当前子树的最大路径和*/
    int curVal = root->val;
    int lmaxSum = maxSum(root->left), rmaxSum = maxSum(root->right);
    if (lmaxSum > 0)
        curVal += lmaxSum;
    if (rmaxSum > 0)
        curVal += rmaxSum;

    if (curVal > maxVal1)
        maxVal1 = curVal;

    /*返回以当前root为根的子树的最大路径和*/
    return GetMax1(root->val, root->val + lmaxSum, root->val + rmaxSum);
}


int maxPathSum(Node* root)
{
    if (root == NULL)
        return 0;

    maxSum(root);
    return maxVal1;
}


int main()
{

    Node* root0 = new    Node(2);
    Node* left01 = new    Node(5);
    Node* right02 = new Node(3);
    Node* left11 = new    Node(6);
    Node* right12 = new Node(2);
    Node* left21 = new    Node(7);
    Node* right22 = new Node(3);
    root0->left = left01;
    root0->right = right02;
    left01->left = left11;
    left01->right = right12;
    right02->left = left21;
    right02->right = right22;
    cout << maxPathSum(root0) << endl;
    return 0;
}

发表于 2019-06-28 10:45:55 回复(0)
/*问题描述:
给定一棵二叉树,求各个路径的最大和,路径可以以任意结点作为起点和终点。
解决思路:
本题可以通过对二叉树进行后序遍历来解决,具体思路如下:
对于当前遍历到的结点root,假设已经求出在遍历root结点前最大的路径和为max:
1)求出以root->left为起始结点,叶子结点为终结点的最大路径和为sumLeft。
2)同理求出以root->right为起始结点,叶子结点为终结点的最大路径和sumRight。
包含root结点的最长路径可能包含如下三种情况:
1)leftMax=root->val+sumLeft(右子树最大路径和可能为负)。
2)rightMax=root->val+sumRight(左子树最大路径和可能为负)。
3)allMax=root->val+sumLeft+sumRight(左右子树的最大路径和都不为负)。
因此,包含root结点的最大路径和为tmpMax=max(leftMax,rightMax,allMax)。
在求出包含root结点的最大路径后,如果tmpMax>max,则更新最大路径和为tmpMax。
*/
#include <iostream> 
#include <limits.h> 
using namespace std;  
struct TreeNode  
{  
    int val;  
    TreeNode *left;  
    TreeNode *right;  
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}  
};  
/*求a,b,c的最大值*/  
int Max(int a, int b, int c)  
{  
    int max = a>b ? a : b;  
    max = max>c ? max : c;  
    return max;  
}  
/*寻找最长路径*/  
int findMaxPathrecursive(TreeNode* root, int &max)  
{  
    if (NULL == root)  
    {  
        return 0;  
    }  
    else  
    {  
        //求左子树以root->left为起始结点的最大路径和  
        int sumLeft = findMaxPathrecursive(root->left, max);  
        //求右子树以root->right为起始结点的最大路径和  
        int sumRight = findMaxPathrecursive(root->right, max);  
        //求以root为起始结点,叶子结点为结束结点的最大路径和  
        int allMax = root->val + sumLeft + sumRight;  
        int leftMax = root->val + sumLeft;  
        int rightMax = root->val + sumRight;  
        int tmpMax = Max(allMax, leftMax, rightMax);  
        if (tmpMax>max)  
            max = tmpMax;  
        int subMax = sumLeft > sumRight ? sumLeft : sumRight;  
        //返回以root为起始结点,叶子结点为结束结点的最大路径和  
        return root->val + subMax;  
    }  
}  
int findMaxPath(TreeNode* root)  
{  
    int max = INT_MIN;  
    int a=findMaxPathrecursive(root, max);  
    cout<<"a:"<<a<<endl;
    return max;  
}  
int main()  
{  
    TreeNode* root0 = new TreeNode(-2);  
    TreeNode* left01 = new TreeNode(-5);  
    TreeNode* right02 = new TreeNode(-3);   
    TreeNode* left11 = new TreeNode(-6);  
    TreeNode* right12 = new TreeNode(-2); 
    TreeNode* left21 = new TreeNode(-7);  
    TreeNode* right22 = new TreeNode(-3);
    root0->left = left01;  
    root0->right = right02;
    left01->left =left11;
    left01->right=right12;
    right02->left=left21;
    right02->right=right22;
    cout << findMaxPath(root0) << endl;  
    return 0;  
} 

发表于 2018-06-08 21:57:17 回复(1)
本题的具体思路,是利用前序遍历的思想,将节点左右两分支的最大都求出来,然后首先判断节点本身作为连接点,连接左右两分支的这个情况是不是比当前max更大,如果更大,更新max;然后将该节点左右两支的最大值返回给上层,供上层进行同样的判定。最终得到最大值。
代码如下:
public class Binary_Tree_Maximum_Path_Sum {
    public int max = Integer.MIN_VALUE;
    public int findRst(TreeNode root){
        if (root == null) {
            return 0;
        } else {
            int sumLeft = findRst(root.left);
            int sumRight = findRst(root.right);
            int cur = root.val;
            int leftRightSum = sumLeft+cur+sumRight;
            max = max<leftRightSum?leftRightSum:max;
            int subMax = sumLeft > sumRight ? sumLeft : sumRight;

            if (cur+subMax > 0) {
                if(max<subMax+cur)
                    max = subMax+cur;
                return cur + subMax;
            } else {
                return 0;
            }
        }
    }
    public int maxPathSum(TreeNode root) {
        if(root==null)
            return 0;
        max = max<root.val?root.val:max;
        findRst(root);
        return max;
    }

    public static void main(String[] args){
        Binary_Tree_Maximum_Path_Sum binary_tree_maximum_path_sum = new Binary_Tree_Maximum_Path_Sum();
        TreeNode root = new TreeNode(2);
        root.left = new TreeNode(-1);
        root.left.left = new TreeNode(-4);
        root.left.right = new TreeNode(99);
        root.right = new TreeNode(-3);
        root.right.left = new TreeNode(-5);
        root.right.right = new TreeNode(-6);
        System.out.println(binary_tree_maximum_path_sum.maxPathSum(root));
    }
}

发表于 2015-02-19 14:06:45 回复(0)
int maxSum = 0;
int maxPathSum(TreeNode *root)
{
     int l,r;
    if (root)
         return 0;
    if (root->left)
        l = maxPathSum(root->left)+root->val;
    if (root->right)
        r = maxPathSum(root->right)+root->val;
    if (l+r-root->val>maxSum)
        maxSum = l+r-root->val;
    return l>r?l:r;
}
发表于 2015-01-29 15:38:12 回复(3)
{
    if( NULL == root ) return 0;

    int num = val;

    num +=  maxPathSum( root->left)
   
    num += maxPathSum( root->rigth);
   return num;
    
}
发表于 2014-11-28 15:04:26 回复(0)
写入速
发表于 2014-11-25 13:31:39 回复(0)