【问题标题】:Binary Search Tree recursion methods二叉搜索树递归方法
【发布时间】:2022-01-30 11:03:40
【问题描述】:

我的任务是搜索并找到二叉搜索树的高度。为了解决这个问题,我想出了以下解决方案。

static int countL = 0 ;
static int countR = 0 ;
public static int getHeight(Node root) {

    if (root.left != null) {
        countL++;

        getHeight(root.left);
    }

    if (root.right != null) {
        countR++;

        getHeight(root.right);
    }

    count = Math.max(countL, countR);

    return count;
}

不是最优雅的,但它解决了某些树的问题。在网上搜索我找到了另一种解决方案。除了更优雅的代码之外,我上面的代码和下面的代码有什么区别?为了成为更精通的编码人员,减少代码行数的最佳方法是什么。我的任务是了解我哪里出错了,以及下面的代码与我的相比有什么不同

private static int getHeight(Node root){
int heightLeft = 0;
int heightRight = 0;

if (root.left != null) {
    heightLeft = getHeight(root.left) + 1;
}
if (root.right != null) {
    heightRight = getHeight(root.right) + 1;
}
return (heightLeft > heightRight ? heightLeft : heightRight);
}

【问题讨论】:

    标签: java recursion binary-search-tree


    【解决方案1】:

    1.实现不正确

    您的实现实际上是不正确的。当countLcountR 都为0 时,它只会在第一次调用getHeight 时起作用。这是因为静态变量与类相关联,而不是对象(如非静态变量)或范围一个函数(如第二个解决方案)。

    说在第一次调用getHeight 之后,countL 是 3,countR 是 4。当你第二次调用它时,这些变量永远不会重置,所以深度树 1 将返回 @ 987654329@.

    最后,getHeight(null) 的解决方案也失败了。

    2。静态变量是一种反模式

    尽可能避免类中的静态变量,因为它们是全局状态。完整说明请参见this thread

    3.第二种解决方案更容易阅读

    如您所见,第二种解决方案更易于阅读。这是出于三个原因:

    1. 所有逻辑都完全包含在函数中,而您的则使用全局状态。
    2. 变量命名更好:heightLeftcountL 更具语义。
    3. 它更短。

    如果您有兴趣,这里有一个更简洁的解决方案:

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

    祝您在 Java 学习冒险中好运!

    【讨论】:

    • 谢谢,只是为了确认一下,如果 root == null,当我们从树中找到叶子时会返回 0 对吗?
    • @jbel 在你的代码中,我认为if (root.left != null) 会抛出一个NullPointerException,因为rootnull 并且没有left 属性。
    • 好吧,这是有道理的。最后,您的解决方案非常优雅。你是怎么想出这个解决方案的?您使用了哪些材料或资源来实现这一点?
    • 练习,练习,练习!和其他技能没什么区别。像这样的问题经常在软件工程面试中被问到,所以那里有很多资源。将书面材料(通过数据结构和算法教科书)、视听材料(大学讲座、Grokking 编码面试、Coursera)和实践练习(leetcode、codechef、hackerrank、代码的出现)健康地组合在一起总是很好)。
    【解决方案2】:

    在您的第一个解决方案中,您正在递增 countL 和 countR 计数器,而不考虑到目前为止您遍历的树的高度。让我们以如下所示的倾斜树为例

       1.   => CountL = 1;  CountR = 0
      /.   
     2.     => CountL = 2;  CountR = 0
    / 
    3.      => CountL = 3;  CountR = 0
     \
      4.    => CountL = 3; CountR = 1
    

    如果您在递增 countR 时查看最后一步,遍历左侧节点所覆盖的高度将被忽略。

    您的第二个解决方案是自下而上的方法,在每个级别,我们比较左右高度并返回最大值

    希望它有助于理解这两种解决方案之间的区别!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 2021-07-03
      • 2019-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多