I have written a code for finding diameter of Binary Tree. Need suggestions for the following:
There are three cases to consider when trying to find the longest path between two nodes in a binary tree (diameter):
The longest path through the root is simply the sum of the heights of the left and right sub-trees (+1 for the root not necessary since the diameter of a tree with a root node and 1 left, 1 right subtree nodes will be 2), and the other two can be found recursively:
public static int getDiameter(BinaryTreeNode root) {
if (root == null)
return 0;
int rootDiameter = getHeight(root.getLeft()) + getHeight(root.getRight()); //Removing the +1
int leftDiameter = getDiameter(root.getLeft());
int rightDiameter = getDiameter(root.getRight());
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
public static int getHeight(BinaryTreeNode root) {
if (root == null)
return 0;
return Math.max(getHeight(root.getLeft()), getHeight(root.getRight())) + 1;
}
One more O(n) solution in python,
code is self explanatory, only issue with this code is it returns tuple containing both height and diameter of the tree.
def diameter(node, height):
if node is None:
return 0, 0
leftheight = 0
rightheight = 0
leftdiameter, leftheight = diameter(node.left, leftheight)
rightdiameter, rightheight = diameter(node.right, rightheight)
rootheight = 1 + max(leftheight, rightheight )
rootdiameter = ( leftheight + rightheight + 1 )
return max( rootdiameter, leftdiameter, rightdiameter ), rootheight
Neat and clean solution:
// way to use below util function:
prop p = new prop();
diameterUtil(root, p);
System.out.println(p.d);
class prop {
int h;
int d;
}
private void diameterUtil(Node n, prop p) {
if (n == null) {
p.h = 0;
p.d = 0;
return;
}
prop lp = new prop();
prop rp = new prop();
diameterUtil(n.left, lp);
diameterUtil(n.right, rp);
p.h = Math.max(lp.h, rp.h) + 1;
p.d = Math.max((lp.h + rp.h + 1), Math.max(lp.d, rp.d));
}
There is a minimal O(n) answer compared to the accepted one.
int DiameterTree(BinaryTreeNode root, int diameter) {
int left, right;
if (!root) return 0;
left = DiameterTree(root.getLeft(), diameter);
right = DiameterTree(root.getRight(), diameter);
if (left + right > diameter) diameter = left + right;
return Math.max(left, right) + 1;
}
Assume diameter
is a static variable in class.
The diameter of a tree T is
Diameter(T) = max( Diameter(T.left), Diameter(T.right), Height(T.left)+Height(T.right)+1 )
private class Data {
public int height;
public int diameter;
}
private void diameter(TreeNode root, Data d) {
if (root == null) {
d.height = 0; d.diameter = 0; return;
}
diameter(root.left, d); // get data in left subtree
int hLeft = d.height;
int dLeft = d.diameter;
diameter(root.right, d); // overwrite with data in right tree
d.diameter = Math.max(Math.max(dLeft, d.diameter), hLeft+d.height+1);
d.height = Math.max(hLeft, d.height) + 1;
}
public int diameter(TreeNode root) {
Data data = new Data();
diameter(root, data);
return data.diameter;
}
Here is a solution in Java that has O(N)
time complexity.
It calculates the height in the same recursion when calculating the diameter.
Reference Link
private class HeightWrapper {
int height = 0;
}
private int getDiameter_helper(BinaryTreeNode root, HeightWrapper wrapper) {
if (root == null) {
return 0; // diameter and height are 0
}
/* wrappers for heights of the left and right subtrees */
HeightWrapper lhWrapper = new HeightWrapper();
HeightWrapper rhWrapper = new HeightWrapper();
/* get heights of left and right subtrees and their diameters */
int leftDiameter = getDiameter_helper(root.left, lhWrapper);
int rightDiameter = getDiameter_helper(root.right, rhWrapper);
/* calculate root diameter */
int rootDiameter = lhWrapper.height + rhWrapper.height + 1;
/* calculate height of current node */
wrapper.height = Math.max(lhWrapper.height, rhWrapper.height) + 1;
/* calculate the diameter */
return Math.max(rootDiameter, Math.max(leftDiameter, rightDiameter));
}
public int getDiameter(BinaryTreeNode root) {
HeightWrapper wrapper = new HeightWrapper();
return getDiameter_helper(root, wrapper);
}