Java 测试二叉树是否平衡的时间复杂性

Java 测试二叉树是否平衡的时间复杂性,java,time-complexity,binary-tree,Java,Time Complexity,Binary Tree,下面的代码测试二叉树是否平衡。我被告知它的运行时间是O(n logn) 据我所知 getHeight()访问每个节点一次,因此是O(n) isBalanced()调用getHeight()。。然后再出现 如果在所有n个节点上调用了isBalanced(),并且它调用了getHeight(),这是O(n),那么复杂性为什么不是O(n²) n表示整个树中的节点数。在这种情况下,在根节点上调用getHeight方法时,该方法仅为O(n)。通常,它是O(m),其中m是您调用getHeighton的节

下面的代码测试二叉树是否平衡。我被告知它的运行时间是O(n logn)

据我所知

  • getHeight()
    访问每个节点一次,因此是O(n)

  • isBalanced()
    调用
    getHeight()
    。。然后再出现

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


n表示整个树中的节点数。在这种情况下,在根节点上调用
getHeight
方法时,该方法仅为O(n)。通常,它是O(m),其中m是您调用
getHeight
on的节点的子树中的节点数;大多数子树都比n小得多。这是你困惑的根本原因

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

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

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

这些总和是2^i*(2^(k-i)-1)中i=0到k-1的总和。每个项约为2^k=n,有k=log_2n项,总复杂度为n*log_2n=O(n logn)。

您所说的是正确的,但不完整。递归多少次?递归isBalanced()是否也会访问树中的每个节点?请浏览代码,查看在最坏的情况下,当树处于平衡状态时,在每个节点上调用递归方法。
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);

}