In Cracking the Coding Interview 6th Edition there\'s a question (4.4) where you\'re suppose to find out if a binary tree is balanced, where balanced in this case means if a
Let's write the time complexity function of isBalanced
as T(n)
. The average-case recurrence relation is therefore:
Where the O(n)
comes from the two calls to getHeight
, which we know to be O(n)
. Therefore, using the Master theorem, the overall complexity of isBalanced
is O(n log n)
.
Your solution does not call isBalanced
on the child nodes, which means the O(n)
in the relation above is replaced by an O(1)
, giving O(n)
overall (again from the Master theorem). It does not however (as an obvious consequence!) check that the child nodes are balanced, so is incorrect.
The problem with CTCI's naive solution is that it effectively calls getHeight
again for each child node (by calling isBalanced
), which is unnecessary. One can incorporate the balance-checking functionality into getHeight
to obtain a solution in O(n)
:
int balance_internal(TreeNode root)
{
// change the specification slightly to return 0 for a leaf
// ... and -1 for an unbalanced node
if (root == null) return 0;
int left_h = balance_internal(root.left);
int right_h = balance_internal(root.right);
// if either node is unbalanced
if (left_h == -1 || right_h == -1)
return -1;
// return max height as before
// ... but now with the knowledge that both child nodes are balanced
return Math.abs(left_h - right_h) > 1 ? -1 : 1 + Math.max(left_h, right_h);
}
boolean isBalanced(TreeNode root)
{
return (balance_internal(root) > -1);
}
Although perhaps not as graceful as the provided solution, this does not create duplicate calls to child nodes, and instead reuses the results from the first set of calls. The recurrence relation is thus the same as that of your own solution, giving O(n)
.