I am working on a simple problem of finding height of a binary tree on HackerRank. My solution below passed all test cases and after some running code by hands, I believe it is an O(n) solution. Most other solutions I found online (I think) said it is O(n) as well, but I am unable to solve the recurrence relation to reach O(n) based on both solutions.
Assuming the tree is not balanced, below is my solution:
public static int height(Node root) {
// Write your code here.
if (root.left == null && root.right == null) {
return 0;
} else if (root.left == null && root.right != null) {
return 1 + height(root.right);
} else if (root.left != null && root.right == null) {
return 1 + height(root.left);
} else {
return 1 + Math.max(height(root.left), height(root.right));
}
}
I found that the number of functions called is almost exact the number of nodes, which means it should be O(n). Based on my last case, which I think is likely to be the worst runtime case when I need to call height(node) on both branches, I tried to derive the following recurrence relation
Let n be the number of nodes and k be the number of level
T(n) = 2 T(n/2)
Base Case: n = 0, n =1
T(0) = -1
T(1) = T(2^0)= 0
Recursive Case:
k = 1, T(2^1) = 2 * T(1)
k = 2, T(2^2) = 2 * T(2) = 2 * 2 * T(1) = 2^2 T(1)
k = 3, T(2^3) = 2^3 * T(1)
....
2^k = n=> k = logn => T(2^k) = 2^k * T(1) = 2^logn * T(1)
So to me apparently, the time complexity is O(2^logn)
, I am confused why people say it is O(n) ? I read this article (Is O(n) greater than O(2^log n)) and I guess it makes sense because O(n) > O(2^logn)
, but I have two questions:
Is my recurrence relation correct and the result correct ? If it is, why in reality ( I count the number of times function is called) I still get O(n) instead of O(2^logn) ?
How do you derive recurrence relation for a recursive function like this ? Do you take the worst case (in my case is last condition) and derive recurrence relation from that ?