天天看點

樹型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;
    }
};
           

繼續閱讀