天天看点

树型DP树型DP

树型DP

算法概论第九周

文章目录

  • 树型DP
    • 题目描述
    • 思路分析
    • 实现代码

124 Binary Tree Maximum Path Sum 题目链接

题目描述

Given a non-empty binary tree, find the maximum path sum.

For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.

Example 1:

Input: [1,2,3]

       1
      / \
     2   3

Output: 6
Example 2:

Input: [-10,9,20,null,null,15,7]

   -10
   / \
  9  20
    /  \
   15   7

Output: 42
           

思路分析

  • 这道题可以采用树型动态规划的方式求解
  • 定义每个节点有一个记录值 m e m mem mem,表示以该点为起点,终点为叶节点的最长路径值
  • m e m mem mem可能连接左子树,也可能连接右子树,也可能仅包含一个点

    m e m [ n o w ] = v a l [ n o w ] + m a x { m e m [ l e f t ] , m e m [ r i g h t ] , 0 } mem[now] = val[now] + max\{mem[left], mem[right],0\} mem[now]=val[now]+max{mem[left],mem[right],0}

  • 题目所求的路径,最多只会有一个“拐点”,即路径有可能包含一个节点的左右及其左右子树
  • 为了计算路径最长,我们可以利用一个变量 h i s t o r y M a x historyMax historyMax来记录递归过程中的最大路径
  • 最长路径可以是左子树构成的mem值对应路径,也可以是右子树构成的mem值对应路径,也可以是左右加顶点构成,也可以仅一个顶点

    h i s t o r y M a x = m a x { h i s t o r y M a x , v a l [ n o w ] , m e m [ l e f t ] , m e m [ r i g h t ] , m e m [ l e f t ] + m e m [ r i g h t ] } historyMax = max\{historyMax,val[now],mem[left],mem[right],mem[left]+mem[right] \} historyMax=max{historyMax,val[now],mem[left],mem[right],mem[left]+mem[right]}

  • 同时,我们可以使用记忆化递归的方式记录 m e m mem mem值,设当前节点索引为 i n d e x index index,左节点为 i n d e x ∗ 2 + 1 index * 2 + 1 index∗2+1,右节点为 i n d e x ∗ 2 + 2 index * 2 + 2 index∗2+2。但由于题目数据刁钻, 最后的AC代码并没有使用记忆化……

实现代码

其中注释掉的部分为记忆化搜索部分

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
// const int MAXNUM = 20000000;
// int mem[MAXNUM];
class Solution {
    int historyMax = -10000000;
public:
    int maxPathSum(TreeNode* root) {
        // for(int i = 0; i < MAXNUM; i++){
        //     mem[i] = -1;
        // }
        findMax(root, 0);
        return historyMax;
    }
    int findMax(TreeNode* root, int ind){
        // if(mem[ind] != -1)
        // return mem[ind];
        if(root == NULL){
            // mem[ind] = 0;
            return 0;
        }
        int maxleft = findMax(root->left, ind * 2 + 1);
        int maxright = findMax(root->right, ind * 2 + 2);
        int res = max(root->val, root->val + max(maxleft, maxright));
        historyMax = max(historyMax, res);
        historyMax = max(historyMax, root->val + maxleft + maxright);
        historyMax = max(historyMax, root->val);
        return res;
    }
};
           

继续阅读