I'm going through the Cracking the Coding Interview book right now and I'm doing a binary tree exercise. There is a snippet of code that is according to the book O(NlogN)
, however, I don't understand why that is. I can understand if the algorithm was O(N)
, but I don't know where the logN
is coming from in their analysis.
int getHeight(TreeNode root) {
if (root == null) return -1; // Base case
return Math.max(getHeight(root.left), getHeight(root.right)) + 1;
}
boolean isBalanced(TreeNode root) {
if (root == null) return true; // Base case
int heightDiff = getHeight(root.left) - getHeight(root.right);
if (Math.abs(heightDiff) > 1) {
return false;
} else {
// Recurse
return isBalanced(root.left) && isBalanced(root.right);
}
}
If we encounter an unbalanced node, we get an early return of false so this is the optimal case. The "worst case" for this algorithm to handle is a completely balanced tree, since we get no early returns of false. For the sake of this example, let's use a perfect binary tree with n nodes.
The first call would trigger getHeight() on each node so ~n nodes are visited. Total work for root level is O(n).
The next two calls (root.left.isBalanced() and root.right.isBalanced()) would trigger getHeight() on subsequent nodes but each one only calls it on ~1/2 n nodes. Total work for 1 height is also O(n).
The next 4 calls would call getHeight on n/4 nodes each. So total work for 2 height is also O(n).
If you see the pattern, the total work for each level of the tree is O(n), so total work for all levels is O(n) * levels in a perfect tree, which comes out to O(nlogn).