【问题标题】:Space complexity on creating an object on recursion递归创建对象的空间复杂度
【发布时间】:2015-06-13 06:53:44
【问题描述】:

checkIfBalanced() 下面代码中的方法如果树是平衡的则返回 true,否则返回 false。然而,在每次递归中,它都会创建 TreeData 对象。在我看来,空间复杂度是 O(1),因为在弹出每个堆栈帧后,在该堆栈帧上创建的对象的引用会丢失并被垃圾收集。 我对吗 ?

请注意:

  1. 我不是在寻找改进/更改我的代码的建议。下面的代码示例是为问我的问题量身定制的。

  2. 另外,please ignore space-complexity adding stack frames。我正在寻找创建的数字“TreeData”对象的空间复杂度。在我看来,任何时候都只有 3 个 TreeData 对象。这就是我要验证的。谢谢。

   private static class TreeData {
        private int height;
        private boolean isBalanced; 

        TreeData(int height, boolean isBalanced) {
            this.height = height;
            this.isBalanced = isBalanced;
        }
    }

    public boolean checkIfBalanced() {
        if (root == null) {
            throw new IllegalStateException();
        }
        return checkBalanced(root).isBalanced;
    }

    public TreeData checkBalanced(TreeNode node) {
        if (node == null) return new TreeData(-1, true);

        TreeData tdLeft = checkBalanced(node.left);
        TreeData tdRight = checkBalanced(node.right);

        if (tdLeft.isBalanced && tdRight.isBalanced && Math.abs(tdLeft.height - tdRight.height) <= 1) {
            return new TreeData(Math.max(tdLeft.height, tdRight.height) + 1, true);
        } 

        return new TreeData(Math.max(tdLeft.height, tdRight.height) + 1, false);
    }

【问题讨论】:

    标签: algorithm recursion space-complexity


    【解决方案1】:

    在我看来,空间复杂度是 O(1),因为在每个堆栈帧之后 弹出,在该堆栈帧上创建的对象的引用是 丢失和垃圾收集。我说的对吗?

    不,你的假设是错误的。 Ray Toal 非常漂亮地解释了这一点。在递归的任何时候,您都必须计算所有保存到内存中的内部堆栈帧,因为空间复杂性考虑了所有辅助空间(额外空间)以及输入(这里不强调)。

    接下来,

    我正在寻找数字“TreeData”对象的空间复杂度 创建的。

    递归程序消耗的最大空间成比例与递归树的最大深度成正比。递归树的最大深度定义为树中最长路径的长度。

    对于给定的程序,程序将从树的根开始,首先开始创建左子树,然后检查右子树。最后,它会返回最长路径的长度以及树是否平衡。

    在我看来,任何时候都只有 3 个 TreeData 对象。这就是我要验证的。

    不,在任何特定的执行时间,首先验证所有左子树,然后验证右子树,因此内存中 TreeData 的对象数将只有 1。它每次都会检查它是否还剩下或右孩子。因此,除了一个之外,所有那些(log n --- 在平衡树的情况下,或 n --- 在退化树的情况下)节点将继续堆积在内存中。在特定时刻,只有 1 个 TreeData 对象处于活动状态,其他对象将暂停并堆叠在内存中,等待轮到它们弹出。

    【讨论】:

    • 所以内存中 TreeData 的对象数量只有 1 - 所以,如果我“忽略堆栈空间”,复杂度会是 O(1) 吗?如果从堆栈中弹出引用,这些对象会被垃圾回收吗?
    • @JavaDeveloper- 1. 如果忽略堆栈空间,只考虑当前引用,那么只有 1 个活动的 TreeData 对象。 2. Maybe/Maybe not,一旦堆栈弹出所有节点,对象可能OR可能不被垃圾回收,这取决于JVM猜测是否它们将在未来被重复使用。为确定起见,您需要通过将这些对象设置为 null 手动执行此操作,以便它们可以收集垃圾。阅读答案(尤其是 Stephen C 的答案)-->stackoverflow.com/questions/27781116/…
    【解决方案2】:

    您在这里没有使用尾递归,而是在向上递归树时构建堆栈帧。公平地说,计算那些堆栈帧。如果您的树是平衡的,那么您将在递归时制作 log n 堆栈帧。在最坏的情况下,对于完全退化的树,您可能有多达 n 个堆栈帧。

    【讨论】:

    • 解释得很漂亮!我希望我可以在你和 Am_I_Helpful 之间分配奖励积分
    【解决方案3】:

    但是在每次递归中,它都会创建 TreeData 对象。

    不正确。您只需在递归的基本情况下创建新的 TreeData 对象。如果您对此感到担忧,为什么不在您可以使用的类中声明一次静态 final TreeData 实例。毕竟,您从该节点传回的唯一内容是 isBalanced 布尔值。

    如果您将方法签名更改为返回布尔值,您也可以直接将布尔值传播回去。

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 1970-01-01
      • 2015-05-13
      • 2017-09-04
      • 2015-05-03
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      相关资源
      最近更新 更多