java - 测试二叉树是否平衡的时间复杂度

标签 java time-complexity binary-tree

下面的代码测试二叉树是否平衡。有人告诉我它的运行时间是 O(n log n)。

据我了解...

  • getHeight() 访问每个节点一次,所以它是 O(n)。

  • isBalanced() 调用 getHeight().. 然后递归

如果 isBalanced() 在所有 n 个节点上调用,并且它调用 getHeight() 这是 O(n),为什么复杂度不是 O(n² )?

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

boolean isBalanced(TreeNode root) {
    if (root == null) return true;
    int heightDiff = getHeight(root.left) - getHeight(root.right);
    if (Math.abs(heightDiff) > 1) 
        return false;
    else
        return isBalanced(root.left) && isBalanced(root.right);

}

最佳答案

n 是指整棵树中的节点数。在这种情况下,当您在根节点上调用 getHeight 方法时,它的时间仅为 O(n)。一般来说,它是 O(m),其中 m 是您调用 getHeight 的节点的子树中的节点数;并且这些子树中的大多数都比 n 小很多。这是您困惑的根本原因。

当左右子树的高度相差 2 或更多时,isBalanced 方法提前返回,不递归。所以我们只需要统计左右高度相差至多为1的节点,即子树平衡的节点的递归调用。在最坏的情况下,所有节点的子树都是平衡的,所以我们永远不会提前停止递归。

鉴于此,让我们假设树是平衡的。然后每个节点调用一次 getHeight,运行时间与节点子树的大小成正比。对于大小为 n = 2^k - 1 的平衡树,有:

  • 2^(k-1)个子树大小为1的叶节点,
  • 2^(k-2) 个大小为 3 的子树,
  • 2^(k-3) 个大小为 7 的子树,
  • ...
  • 2^i 个大小为 2^(k-i) - 1 的子树,
  • ...
  • 2 个大小为 2^(k-1) - 1 的子树,
  • 1 个大小为 2^k - 1 = n 的子树。

它们的总和是 i = 0 到 k-1 的 2^i * (2^(k-i) - 1) 的总和。每个项大约是 2^k = n,并且有 k = log_2 n 个项,总复杂度为 n * log_2 n = O(n log n)。

关于java - 测试二叉树是否平衡的时间复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58987491/

相关文章:

recursion - 动态规划: Tabular vs memoization

c++ - T(n)嵌套循环

performance - Haskell 中的素筛

计算二叉搜索树中的比较次数

java - java中如何解码URL实体?

java - 为什么我需要将私有(private)类声明为静态以避免 "Generic Array Creation"错误?

java - JTextField 与 JComboBox 无法正常工作

java - 是否有任何 "strategies"来解决二叉树问题?

java - 什么时候需要回溯?

java - 在移动应用程序测试期间无法使用属性文件将值传递到所需的输入字段