微软面试题: LeetCode 124. 二叉树中的最大路径和 出现次数:4
8
/ \
-3 7
/ \
1 4
最大路径:4 -> -3 -> 8 ->7 res = 16
看到二叉树的题,首先尝试使用递归来分析。一棵 二叉树的最大路径有 3 种 情况:
1. 最长路径 不包含根节点 8 ,全在左子树中;
2. 最长路径 不包含根节点 8,全在右子树中;
3. 最长路径包含根节点 8,则最大路径 在左、右 子树中若有片段,那一定都是单枝树;
假设我们只考虑 第三种情况 ,代码如下:
int maxPathSum(TreeNode* root) { int left_path = max(helper(root->left) ,0); int right_path = max(helper(root->left) ,0); return root->val + left_path + right_path; } //返回经过root的单边分支最大和给 root的父节点计算使用 int helper(TreeNode* root) { if(root == NULL) { return 0; } //计算左边分支最大值,左边分支如果为负数还不如不选择 int left = max(helper(root->left),0); //计算右边分支最大值,右边分支如果为负数还不如不选择 int right = max(helper(root->right),0); // 返回经过root的单边最大分支给当前root的父节点计算使用 return root->val + max(left,right); }
从以上代码可以看出,求经过根结点的最大路径,最终根结点的左子树和右子树中的最大路径都是一个单支树或者不选;
上面只考虑了包含最初根节点 8
的路径。那如果不包含当前根节点,而是其他的路径呢?
从上面的代码中可以发现,对二叉树 root 和它的左右子树的处理是不一样的。递归函数 helper 递归地处理 root 的左右子树,
递归地返回 左右子树中的最大单边分支给其父节点处理。
使用一个 变量保存二叉树在后序遍历过程中的最大路径和。
最终 代码如下:
1 class Solution { 2 private: 3 int res = INT_MIN; 4 public: 5 int maxPathSum(TreeNode* root) 6 { 7 helper(root); 8 return res; 9 } 10 //返回经过root的单边分支最大和给 root的父节点计算使用 11 //递归函数是一个后序遍历算法 12 int helper(TreeNode* root) 13 { 14 if(root == NULL) 15 { 16 return 0; 17 } 18 //计算左边分支最大值,左边分支如果为负数还不如不选择 19 int left = max(helper(root->left),0); 20 //计算右边分支最大值,右边分支如果为负数还不如不选择 21 int right = max(helper(root->right),0); 22 //在递归地后序遍历二叉树过程中,left->root->right 记录了 二叉树所有可能的路径 23 //与已经计算过历史最大值做比较 24 res = max(res,root->val + left + right); 25 // 返回经过root的单边最大分支给当前root的父节点计算使用 26 //当遍历到 二叉树的根节点时,左右子树已经遍历结束,此时res 中已经记录了 27 //左子树中的最大路径和右子树中的最大路径两者之间大的一个,此时此时的res 再和 28 //包含根节点的情况比较。 29 return root->val + max(left,right); 30 } 31 };