未通过所有测试用例的二叉树的最大路径

Posted

技术标签:

【中文标题】未通过所有测试用例的二叉树的最大路径【英文标题】:Maximum Path of a Binary tree not passing all the test cases 【发布时间】:2021-12-11 10:39:09 【问题描述】:

我正在尝试解决这个 Leetcode 问题:Binary Tree Maximum Path Sum. 我知道这个问题有很多 SO 答案。但我找不到与我的问题相关的任何内容。因此,在深入研究代码之前,我想简要介绍一下我是如何编写算法的。

If I am at a particular node, I considered the following cases.
 Case 1: The maximum path is somewhere inside the left subtree (not including the current node)
 Case 2: The maximum path is somewhere inside the right subtree (not including the current node)
 Case 3: The maximum path starts from the current node and ends somewhere in the left subtree
 Case 4: The maximum path starts from the current node and ends somewhere in the right subtree
 Case 5: The maximum path is the current node itself.
 Case 6: The maximum path starts somewhere in the left subtree, goes through the current node, and ends somewhere in the right subtree.

这里是代码:

var maxPathSum = function(root) 
    if (root.left === null && root.right === null) 
        return root.val;
    
    
    // Case 1: Max sum is in the left subtree (not including the root)
    let leftPathSum = 0;
    if (root.left) 
        leftPathSum = maxPathSum(root.left);
    
     // Case 2: Max sum is in the right subtree (not including the root)
    let rightPathSum = 0;
    if (root.right) 
        rightPathSum = maxPathSum(root.right);
    
     
    
    // Case 3: root + leftPathSum
    let leftSumWithRoot = leftPathSum + root.val; 
    // Case 4: root + rightPathSum
    let rightSumWithRoot = rightPathSum + root.val; 
    
    let maxWithRoot = Math.max(leftSumWithRoot, rightSumWithRoot); 
    let maxWithoutRoot = Math.max(leftPathSum, rightPathSum); 
    
    let maxSoFar = Math.max(maxWithRoot, maxWithoutRoot); 
    
    // Case 5: Root with alone
    maxSoFar = Math.max(maxSoFar, root.val); 
    
    // Case 6: Max path goes through the root
    let maxThroughRoot = leftSumWithRoot + rightSumWithRoot - root.val;
    
    return Math.max(maxThroughRoot, maxSoFar);
    
;

我得到了一些测试用例通过,一些没有通过,尤其是那些具有负值的测试用例。我知道我的算法很可能有问题,但是有人可以帮我解决我的想法错误的方向。我看到了这个问题的不同解决方案。在某些解决方案中,他们将 ma​​xPathSum(node.left) 和 maxPathSum(node.right) 与 0 进行比较,问题与此有关吗?此外,在其他一些解决方案中,他们没有考虑左右子树内的 maxPathSum。我不应该这样做吗?如果有人让我知道我在哪里做错了,我将非常感激。提前致谢。

【问题讨论】:

你看过失败的测试用例了吗?将代码粘贴到 Leetcode 中,失败的测试用例发生在树中的所有值都为负时,但您返回 0。想想如果所有树节点都有负值,答案应该是什么。 @kcsquared 你是对的。我想到了这一点,但不幸的是无法弄清楚如何处理 0 。另外,我写的案例有什么问题吗?你看到那里有什么问题吗?顺便说一句,谢谢你的回复。 案例没问题;在路径不能为空的问题中有一个未说明的假设。 @kcsquared 知道了。尽管我不确定我是否正确理解了它,但我会按照您的说法进行调查。再次感谢。 :-) 【参考方案1】:

您的代码在此输入中失败:[-2,-1]

图表如下所示:

   -2
   /
 -1

所以,let maxWithoutRoot = Math.max(leftPathSum, rightPathSum); 将是 0。然后 maxSoFar 将是零,所以最终你的输出是 0。如果我组织你的代码:

var maxPathSum = function(root) 
    let res=root.val
    function dfs(node)
        if (node===null)
            return 0
        
        let left=dfs(node.left)
        let right=dfs(node.right)
        // ignoring negatives. looking for max, so if left or right is negative, do not add it
        let leftMax=Math.max(left,0)
        let rightMax=Math.max(right,0)
        res=Math.max(node.val+leftMax+rightMax,res)
        return node.val+Math.max(leftMax,rightMax)
    
    dfs(root)
    return res
;

【讨论】:

感谢您的回复。我有个问题。为什么我们忽略左右子树上的负数?如果树只包含负数,我们将负值与 0 进行比较,我们将如何得到正确的结果?而在dfs函数中,为什么我们不直接返回res呢? @h_a 否定总是会减少总数。

以上是关于未通过所有测试用例的二叉树的最大路径的主要内容,如果未能解决你的问题,请参考以下文章

55 二叉树的深度

Offer[37] 序列化二叉树

树的高度

测试用例编写思路

基础哈夫曼树-最简单的

DS树--二叉树之最大路径