【问题标题】:Height of a binary tree二叉树的高度
【发布时间】:2010-12-25 19:47:50
【问题描述】:

考虑以下代码:

public int heightOfBinaryTree(Node node)
{
    if (node == null)
    {
        return 0;
    }
    else
    {
        return 1 +
        Math.max(heightOfBinaryTree(node.left),
            heightOfBinaryTree(node.right));
    }
}

我想知道这段代码背后的逻辑推理。人们是怎么想出来的?有些人有归纳证明吗?

此外,我想只用二叉树的根作为参数进行 BFS 以获得二叉树的高度。以前的方法比我的好吗?为什么?

【问题讨论】:

  • 在 null 情况下不需要将 0 更改为 -1

标签: java algorithm tree


【解决方案1】:
if (node == null)
{
    return 0;
}

叶节点的子节点是null。因此,这就是说,一旦我们经过叶子,就没有更多的节点了。

如果我们没有经过叶子节点,我们必须计算高度,这段代码递归地计算。

return 1 +

当前节点在当前正在计算的子树的高度上加一高度。

    Math.max(heightOfBinaryTree(node.left),
        heightOfBinaryTree(node.right));

我们递归地计算左子树(node.left)和右子树(node.right)的高度。由于我们正在计算最大深度,因此我们取这两个深度中的最大值。

我已经在上面证明了递归函数是正确的。所以调用父节点上的函数会计算整棵树的深度。

这是来自this document 的树高的图形表示。 h 是树的高度,hlhr 分别是左右子树的高度。

此外,我想只是做一个 BFS 与二叉树的根 作为获得高度的论据 二叉树。是上一个 方法比我好?为什么?

您提供的代码是 DFS 的一种形式。由于您必须处理所有节点才能找到树的高度,因此 DFS 和 BFS 之间没有运行时差异,尽管 BFS 将使用 O(N) 内存,而 DFS 将使用 O(logN) 内存。 BFS 的代码也稍微复杂一些,因为它需要一个队列,而 DFS 使用“内置”递归堆栈。

【讨论】:

  • 为什么if后面还有其他的?我以为 return 会退出函数!
  • else 块在此场景中仅用于可读性目的。您只能拥有带有return 0;if 块并返回它下面的递归函数。结果是一样的。
  • @marcog 我遇到了这个非常古老的帖子。只是好奇节点是否为 NULL 值应该是 0 还是 -1 ?
  • 我想我得到了答案 - 这将取决于我们是将高度视为节点数还是边数。
  • 是不是需要像这样修改它以避免在叶子处添加不必要的1............ if (t == null) { return 0; } else if (t.left == null && t.right == null) { return 0; } else { return 1 + Math.max(height(t.left), height(t.right)); }
【解决方案2】:

该代码背后的逻辑是:

由于一个节点将有两个孩子,因此树的高度将是根为左孩子和右孩子的树的高度中的最大值,当然对于孩子的步行也是 +1。

如您所见,上面的描述是递归的,代码也是如此。

BFS 也应该这样做,但从实现和空间/时间复杂度来看,这将是一种过度杀伤。

有一种说法,递归函数虽然难以理解,但实现起来却非常优雅。

【讨论】:

    【解决方案3】:

    一棵树的高度是从它的根开始的最长向下路径的长度。 此函数是一种计算二叉树层数的递归方法。它只是在下降树时递增计数器,返回最大计数器(最低节点上的计数器)。

    我希望我有所帮助。

    【讨论】:

      【解决方案4】:

      这是一个递归函数。意思是一棵树的高度是 1 + 它最高的树枝的高度。

      BFS 是广度优先搜索吗?我不确定效率会有什么不同,但我喜欢递归函数的简单性。

      【讨论】:

        【解决方案5】:

        更多地扩展答案并详细说明递归和递归调用堆栈。

        假设树

              2
             /\
            5  9
           /
          0 
        

        让我们先假设左子树,root(2) 在左子树上调用heightOfBinaryTree 方法

        相关方法的调用栈如下

        node(5) calls node(0)
        node(0) calls node(null)
        node(null) breaks the recursive loop
        

        考虑到这些调用是在方法返回任何内容之前进行的。

        在递归调用堆栈上迭代,这是每个节点返回其输出的地方。

        node(null) returned 0 -> 0
        node(0) returned (return from node(null) + 1) -> 1
        node(5) returned (return from node(0) + 1) -> 2
        

        右子树也是如此。如果我们比较左右子树的输出,我们将得到高度。

        【讨论】:

          猜你喜欢
          • 2021-09-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多