2

The code below tests whether a binary tree is balanced. I have been told that its running time is O(n log n).

To my understanding...

  • getHeight() visits every node once, so it is O(n).

  • isBalanced() calls getHeight().. then recurse

If isBalanced() is called on all n nodes, and it calls getHeight() which is O(n), why isn't the complexity 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);

}
4
  • What you said is true but incomplete. Recurse how many times? Commented Nov 22, 2019 at 4:32
  • would recursing isBalanced() not visit every node in tree as well? Commented Nov 22, 2019 at 4:37
  • Please trave through the code and see Commented Nov 22, 2019 at 4:39
  • The recursive method is called on every node in the worst case, when the tree is balanced. Commented Nov 22, 2019 at 5:03

1 Answer 1

6

By n, you mean the number of nodes in the whole tree. In that case, the getHeight method is only O(n) when you call it on the root node. In general, it is O(m) where m is the number of nodes in the subtree of the node you call getHeight on; and most of those subtrees are a lot smaller than n. This is the root cause of your confusion.

The isBalanced method returns early, without recursing, when the left and right subtrees differ in height by 2 or more. So we only need to count recursive calls for the nodes with left and right heights differing by at most 1, i.e. nodes whose subtrees are balanced. In the worst case, all nodes' subtrees are balanced so we never get to stop recursing early.

Given that, let's assume the tree is balanced. Then getHeight is called once per node, and has a running time proportional to the size of the node's subtree. For a balanced tree of size n = 2^k - 1, there are:

  • 2^(k-1) leaf nodes whose subtree size is 1,
  • 2^(k-2) subtrees of size 3,
  • 2^(k-3) subtrees of size 7,
  • ...
  • 2^i subtrees of size 2^(k-i) - 1,
  • ...
  • 2 subtrees of size 2^(k-1) - 1,
  • 1 subtree of size 2^k - 1 = n.

The sum of these is the sum for i = 0 to k-1 of 2^i * (2^(k-i) - 1). Each term is approximately 2^k = n, and there are k = log_2 n terms, giving a total complexity of n * log_2 n = O(n log n).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.