首页 > 试题广场 >

二叉树中的最大路径和

[编程题]二叉树中的最大路径和
  • 热度指数:1611 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
二叉树里面的路径被定义为:从该树的任意节点出发,经过父=>子或者子=>父的连接,达到任意节点的序列。
注意:
1.同一个节点在一条二叉树路径里中最多出现一次
2.一条路径至少包含一个节点,且不一定经过根节点

给定一个二叉树,请你计算它的最大路径和
例如:
给出以下的二叉树,

最优路径是:2=>1=>3,或者3=>1=>2,最大路径和=2+1+3=6

数据范围:节点数满足 ,节点上的值满足
要求:空间复杂度 ,时间复杂度

输入描述:
第一行输入一个正整数 n 表示二叉树的节点数
第二行输入 n 个整数表示二叉树上第 i 个节点的值
第三行输入 n 个整数表示二叉树上第 i 个节点的父节点是第几个节点,(其中第一个节点是根节点,其父节点表示为第零个节点0)。


输出描述:
输出最大路径和
示例1

输入

3
1 2 3
0 1 1

输出

6
示例2

输入

5
-20 8 20 15 6
0 1 1 3 3

输出

41

说明

其中一条最大路径为:15=>20=>6,路径和为15+20+6=41   
示例3

输入

2
-2 -3
0 1

输出

-2
咱们来个短的
s[i]——i节点为起点的所有向下的子路径中的最大路径和。
#include<iostream>
using namespace std;
int n,v[100009],p[100009],s[100009],r=-0x3f3f3f3f;
int main(){
  cin>>n;
  for(int i=1;i<=n;i++) cin>>v[i];
  for(int i=1;i<=n;i++) cin>>p[i];
  for(int i=1;i<=n;i++) s[i]=v[i];
  for(int i=n;i>=1;i--) s[p[i]]=max(s[p[i]],v[p[i]]+s[i]);
  for(int i=1;i<=n;i++) v[p[i]]+=s[i];  
  for(int i=1;i<=n;i++) r=max(r,max(v[i],s[i]));
  cout<<r<<endl;
}


发表于 2022-09-03 16:40:06 回复(0)
#include<bits/stdc++.h>
using namespace std;

struct TreeNode{
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode():val(0),left(nullptr),right(nullptr){}
    TreeNode(int _val):val(_val),left(nullptr),right(nullptr){}
    TreeNode(int _val, TreeNode* _left, TreeNode* _right) : val(_val), left(_left), right(_right) {}
};

vector<TreeNode*> myMap;
void buildTree(vector<int>& values, vector<int>& fathers){
    int n = values.size();
    if(n == 0) return;
    for(auto val : values){
        myMap.push_back(new TreeNode(val));
    }
    for(int i = 1; i < n; i++){
        if(!myMap[fathers[i] - 1]->left){
            myMap[fathers[i] - 1]->left = myMap[i];
        }
        else{
            myMap[fathers[i] - 1]->right = myMap[i];
        }
    }
}

class Solution {
public:
    int ans;
    int maxPathSum(TreeNode* root) {
        ans = INT_MIN;
        dfs(root);
        return ans;
    }

    int dfs(TreeNode* root){
        if(root == nullptr) return 0;//遇到空节点返回0
        int leftValue = dfs(root->left);
        int rightValue = dfs(root->right);
        //更新最大路径和(注意4种更新方式)
        if(leftValue >= 0 && rightValue <= 0){//情况1
            ans = max(ans, leftValue + root->val);
            return leftValue + root->val;
        }
        if(leftValue <= 0 && rightValue >= 0){//情况2
            ans = max(ans, rightValue + root->val);
            return rightValue + root->val;
        }
        if(leftValue >= 0 && rightValue >= 0){//情况3
            ans = max(ans, leftValue + rightValue + root->val);
            return max(leftValue, rightValue) + root->val;
        }
        ans = max(ans,root->val);//情况4
        return root->val;
    }
};


int main(){
    int n;
    while(cin >> n){
        vector<int> values(n);
        vector<int> fathers(n);
        for(int i = 0; i < n; i++){
            cin >> values[i];
        }
        for(int i = 0; i < n; i++){
            cin >> fathers[i];
        }
        buildTree(values, fathers);
        Solution s;
        cout << s.maxPathSum(myMap[0]) << endl; 
        myMap.clear();
    }
}
发表于 2022-03-06 23:21:06 回复(0)
讨论情况这里卡了很久……
#include <climits>
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cstring>
using namespace std;

int dp[100002];
int res = INT_MIN;

int dfs(int x, unordered_map<int, vector<int>>& list, vector<int>& value) {
    if (list.find(x) == list.end()) { //叶节点返回本身
        dp[x] = value[x];
        res = max(res,dp[x]);
        return dp[x];
    }
    if (dp[x] != 0) return dp[x];
    auto temp = list[x];
    int left = dfs(temp[0], list, value), right=0;
    if (temp.size() == 2) {
        right = dfs(temp[1], list, value);
    }
    dp[x] = max(max(right, left)+value[x],value[x]);
        res = max(res,max(right, left));
        res = max(res,max(dp[x], right+left+value[x]));
    return dp[x];
}

int main() {
    int n;
    cin >> n;
    vector<int> value(n + 1);
    unordered_map<int, vector<int>> list;
    for (int i = 1; i <= n; i++) cin >> value[i];
    for (int i = 1; i <= n; i++) {
        int parent;
        cin >> parent;
        if (list.find(parent) != list.end()) {
            list[parent].push_back(i);
        } else {
            list.insert({parent, {i}});
        }
    }
    memset(dp, 0, sizeof(dp));
    dfs(1, list, value);
    cout <<res;
}


编辑于 2024-01-04 15:32:32 回复(0)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010, INF = 0x3fffffff;
int v[N], ne[N], h[N], a[N], w[N];
int idx, ans;

void add(int a, int b){
    v[idx]=b, ne[idx]=h[a], h[a]=idx++;
}

int dfs(int u){
    int d1 = 0, d2 = 0;//d1,d2分别代表以u为根节点的所有子树的最大与次大路径和,路径为负就不选,初始化为0
    for(int i=h[u]; i!=-1; i=ne[i]){
        int j=v[i];
        int d = dfs(j)+w[j];
        if(d >= d1) d2 = d1, d1 = d;
        else if(d > d2) d2 = d;
    }
    ans = max(ans, d1+d2+w[u]);
    return d1;
}

int main() {
    memset(h, -1, sizeof h);
    idx = 0, ans = -INF;
    int n;
    cin >> n;
    for(int i=1; i<=n; i++)cin >> w[i];
    for(int i=1; i<=n; i++){
        int id;
        cin >> id;
        add(id, i);
    }
    dfs(1);
    cout << ans << endl;
    return 0;
}

发表于 2023-02-09 16:30:49 回复(0)
#include<bits/stdc++.h>
using namespace std;
struct Node{
    int val;
    Node* left;
    Node* right;
    Node(int _v):val(_v),left(nullptr),right(nullptr){}
};
int res = INT_MIN;
int fun(Node* root){
    if(!root) return 0;
    int left = max(fun(root -> left),0);
    int right = max(fun(root -> right),0);
    res = max(res,left + right + root -> val);
    return max(root -> val + left,root -> val + right);
    
}
int main(){
    int n ;
    cin >> n;
    int value;
    vector<Node*> node;
    for( int i = 0; i < n; i++){
        
        cin >> value;
        auto temp = new Node(value);
        node.push_back(temp);
    }
    Node* root;
    for( int i = 0; i < n; i++){
        cin >> value;
        if(value == 0){
            root = node[i];
            continue;
        }
        if(! node[value - 1] -> left){
            node[value - 1] -> left = node[i];
        }else{
            node[value - 1] -> right = node[i];
        }
    }
    fun(root);
    cout<<  res;
    return 0;
    
}

发表于 2022-03-05 15:29:33 回复(0)
import java.util.*; 

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static class Node {
        public Node(int val) {
            this.val = val;
        }
        public int val;
        public Node left;
        public Node right;
    }
    public static int ans = Integer.MIN_VALUE;
    public static Map<Integer, Node> map = new HashMap<>();
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int nodeNum = in.nextInt();
        in.nextLine();
        if (nodeNum == 0) {
            return;
        }
        int[][] child = new int[nodeNum][2];
        String[] strings1 = in.nextLine().split(" ");
        String[] strings2 = in.nextLine().split(" ");
        for (int i = 1; i <= nodeNum; i++) {
            map.put(i, new Node(Integer.valueOf(strings1[i-1])));
            if (map.get(Integer.valueOf(strings2[i-1])) != null) {
                if (map.get(Integer.valueOf(strings2[i-1])).left == null) {
                    map.get(Integer.valueOf(strings2[i-1])).left = map.get(i);
                } else {
                    map.get(Integer.valueOf(strings2[i-1])).right = map.get(i);
                }
            }
        }

        
        Node root = map.get(1);
        dfs(root);
        System.out.println(ans);
    }

    public static int dfs(Node root) {
        if (root == null) {
            return 0;
        }
        int maxL = Math.max(dfs(root.left), 0);
        int maxR = Math.max(dfs(root.right), 0);

        ans = Math.max(ans, root.val + maxL + maxR);
        return Math.max(root.val + maxL, root.val + maxR);
    }
}

发表于 2024-01-13 23:18:16 回复(0)
#include <bits/stdc++.h>
#include <climits>
using namespace std;

int n;
vector<int> value;
vector<int> parent;
vector<int> lchild;
vector<int> rchild;
int ans = INT_MIN;

int dp(int root){
    // 空节点返回 0
    if(root == -1)
        return 0;
   
    int lroot = lchild[root];
    int rroot = rchild[root];
    int cval = value[root];
    int lval = dp(lroot);
    int rval = dp(rroot);

    //如果root的值小于0,则可以舍弃root的值不选择而返回0
    int res = max(0, cval);
    // 否则,只能选左分支或者右分支的值返回
    res = max(res, lval + cval);
    res = max(res, rval + cval);

    // 对于答案来说,当前节点的最优答案是左 + 中 + 右
    ans = max(ans, rval + lval + cval);

    return res;
}

int main() {
    cin >> n;
    value.resize(n + 1, 0);
    parent.resize(n + 1, -1);
    lchild.resize(n + 1, -1);
    rchild.resize(n + 1, -1);
    int root = -1;
    for(int i = 1; i <= n; i ++){
        int c;
        cin >> c;
        value[i] = c;
    }

    for(int i = 1; i <= n; i ++){
        int p;
        cin >> p;
       
        if(p == 0) root = i;

        parent[i] = p;
        if(lchild[p] == -1){
            lchild[p] = i;
        }else{
            rchild[p] = i;
        }
       
    }
    /*
    for(auto p : parent)
        cout << p << " ";
    cout << endl;
    for(auto l : lchild)
        cout << l << " ";
    cout << endl;
    for(auto r : rchild)
        cout << r << " ";
    cout << endl;*/
    dp(root);
    cout << ans;

}
// 64 位输出请用 printf("%lld")
发表于 2023-08-13 17:18:39 回复(0)
import java.util.*;
public class Main {
    static int maxSum = Integer.MIN_VALUE;
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        int[] nodeVal = new int[n];
        for (int i = 0; i < n; i++) {
            nodeVal[i] = scan.nextInt();
        }
        int[] parent = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = scan.nextInt();
        }
        TreeNode root = buildTree(nodeVal, parent);
        maxPathSum(root);
        System.out.println(maxSum);
    }
    
    public static TreeNode buildTree(int[] nodeVal, int[] parent) {
        TreeNode[] nodes = new TreeNode[nodeVal.length];
        for (int i = 0; i < nodeVal.length; i++) {
            TreeNode node = new TreeNode(nodeVal[i]);
            nodes[i] = node;
        }
        TreeNode root = nodes[0];
        for (int i = 1; i < parent.length; i++) {
            TreeNode curNode = nodes[i];
            TreeNode parentNode = nodes[parent[i] - 1];
            if (parentNode.left == null) {
                parentNode.left = curNode;
            } else {
                parentNode.right = curNode;
            }
        }
        return root;
    }
    
    public static int maxPathSum(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftGain = Math.max(maxPathSum(root.left), 0);
        int rightGain = Math.max(maxPathSum(root.right), 0);
        int priceNewpath = root.val + leftGain + rightGain;
        maxSum = Math.max(maxSum, priceNewpath);
        return root.val + Math.max(leftGain, rightGain);
    }
    
    static class TreeNode {
        TreeNode left;
        TreeNode right;
        int val;
        public TreeNode(int val) {
            this.val = val;
        }
    }
}

发表于 2022-08-05 11:16:33 回复(0)

leecode 124题,可以100%通过,牛客网不行,有点奇怪哦;
我觉得难点在于构造二叉树吧,leecode是核心代码模式,acm要自己构造二叉树,挺难受的。

while(line = readline()){
    var n = parseInt(line);
    var node = readline().split(' ').map(Number);
    var fa = readline().split(' ').map(Number);
    deal(n,node,fa);

}
function deal(n,node,f){
    var root = construct_bst(n,node,f);
     var res = -1000;
    maxDepth(root);
    console.log(res)
    function maxDepth(root){
        if(root == null) {
            return 0;
        }
        var left = maxDepth(root.left);
        var right = maxDepth(root.right);
        res = Math.max(res, left+right+root.val);
        // 返回当前子树的路径和 分为走左边、右边、不动 3种情况
        var sum = root.val+Math.max(0,left,right);
        return sum < 0 ? 0 : sum;
    }
}
function TreeNode(val){
    this.val = val;
    this.left = null;
    this.right = null;
}
function construct_bst(n,node,fa){
   var Node = [];
    for(var i = 0; i < n; i++){
        var temp = new TreeNode(node[i]);
        Node.push(temp);
    }
    var root = Node[0];
    for(var i = 1; i < n; i++){
        if(!Node[fa[i]].left) {
            Node[fa[i]-1].left = Node[i]
        } else{
            Node[fa[i]-1].right = Node[i]
        }
    }
    return root;
}
发表于 2022-05-20 10:54:18 回复(0)
建议直接做leetcode124,牛客的这题测试样例漏判了
 

编辑于 2022-03-05 08:10:18 回复(6)
这题应该先要拓扑排序,得到拓扑序列即是DP顺序,然后再用动态规划,不然从根节点走只能深度优先.
发表于 2022-02-13 04:31:11 回复(0)
这个题就没人做吗...
发表于 2022-02-11 12:22:01 回复(0)

问题信息

难度:
12条回答 2514浏览

热门推荐

通过挑战的用户

查看代码