如何在二叉树中找到最长的连续路径

时间:2017-08-13 17:28:56

标签: algorithm data-structures tree binary-tree

我在接受采访时被问到这个问题。考虑二叉树,我们需要打印最长路径的长度,其中每个元素相差1。

EG:

          6
        /   \  
      5       7
     / \     / \
    2   4   8   9
回答:5 (4,5,6,7,8)

怎么做? 我开发了一个algoirthm来打印从根到叶的增加路径,但我不是要开发一个跟踪两个子树上的路径的路径。

编辑:修改后需要取回原始树。

4 个答案:

答案 0 :(得分:2)

正如@qwertyman在评论中所建议的

  1. 删除所有无效边,即差异大于1的边

  2. 现在我们有一个森林,为每个森林计算直径,因为它在@FilipKočica解决方案中给出

  3. 答案是所有森林的最大直径

答案 1 :(得分:1)

对于每个子树,您可以计算从子树根向下延伸的最长路径,向下延伸最长路径,以及从子树中任何位置的同一节点向下增加和减少路径组成的最长内部路径。

如果您已经为所有子节点创建了这些节点,则很容易计算它们,因此您可以将其作为任何后序遍历的一部分。

答案是整棵树内最长的内部路径。

答案 2 :(得分:1)

答案不正确 - 另一位用户正确指出了一个错误。我的解决方案仅在最大长度路径通过根时才起作用。例如,如果最大长度路径完全在左子树中并且没有通过根,则此答案将失败。请随意阅读以熟悉递归解决方案......以及其中的错误。

我假设路径必须具有+1的差异并不重要,如您的示例所示。差异为-1,导致类似4 -> 5 -> 4 -> 3 -> 4 -> 5的路径也可以。

public int getLongestConsecutivePath(TreeNode root) {
    return root == null
        ? 0
        : getLength(root.left, root.value) + getLength(root.right, root.value);
}

private int getLength(TreeNode node, int prevVal) {
    return node == null || Math.abs(node.value - prevVal) > 1
        ? 0
        : Math.max(getLength(node.left, node.value), getLength(node.right, node.value)) + 1;
}

<强>解释

  • 如果root不为null,我们将得到左右子树的最大长度并将其相加。
  • 要获得子树中的最大长度,我们递归地获得子树的右侧和左侧子树的最大长度。
    • 如果我们到达了叶子,或者如果我们到达了一个值差异大于1的节点,我们返回0.
    • 否则,我们递归地从左右子树获取最大长度,并为其添加1以适应此节点本身。

答案 3 :(得分:1)

longest_desc[a]成为从a下降的最长1-by-1下行路径 类似地longest_asc[a],从

开始的最长1-by-1增量路径

对于固定的根R,答案为longest_desc[R] + longest_asc[R] - 1

一个强制解决方案将从每个节点X执行2次dfs / bfs遍历以计算longest_asc[X] and longest_desc[X],然后将它们合并在一起。产生的运行时复杂性为O(n^2)

但我们实际上可以使用动态编程做得更好:

longest_asc[X] = max(longest_asc[Y in children[X]] with Y = X + 1)
longest_desc[X] = max(longest_desc[Y in children[X]] with Y = X - 1)

然后我们可以计算单个DFS遍历中的所有值=&gt; O(n)解决方案。