Given a Binary Tree, find the deepest leaf node that is left child of its parent. This question is attributed to GeeksForGeeks. Looking for code-review, optimizations and best practices.
public class DeepestLeftLeaf<T> {
private TreeNode<T> root;
/**
* Constructs a binary tree in order of elements in an array.
* After the number of nodes in the level have maxed, the next
* element in the array would be a child of leftmost node.
*/
public DeepestLeftLeaf(List<T> items) {
create(items);
}
private void create (List<T> items) {
root = new TreeNode<T>(items.get(0));
final Queue<TreeNode<T>> queue = new LinkedList<TreeNode<T>>();
queue.add(root);
final int half = items.size() / 2;
for (int i = 0; i < half; i++) {
if (items.get(i) != null) {
final TreeNode<T> current = queue.poll();
final int left = 2 * i + 1;
final int right = 2 * i + 2;
if (items.get(left) != null) {
current.left = new TreeNode<T>(items.get(left));
queue.add(current.left);
}
if (right < items.size() && items.get(right) != null) {
current.right = new TreeNode<T>(items.get(right));
queue.add(current.right);
}
}
}
}
private static class TreeNode<T> {
private TreeNode<T> left;
private T item;
private TreeNode<T> right;
TreeNode (T item) {
this.item = item;
}
}
/**
* Returns the deepest left-leaves.
* If two such left-child-leaves are at equidistant, we chose the leftmost among them in the tree.
*
* @return the item which is deepest.
*/
public T leftNode() {
if (root == null) {
throw new IllegalStateException("The root cannot be null.");
}
return recurse(root).item;
}
private static class Data<T> {
private int count;
private T item;
Data (int count, T item) {
this.count = count;
this.item = item;
}
}
private Data<T> recurse(TreeNode<T> node) {
if (node == null) return null;
Data<T> data1;
if (node.left != null && node.left.left == null && node.left.right == null) {
data1 = new Data<>(1, node.left.item);
} else {
data1 = recurse(node.left);
}
Data<T> data2 = recurse(node.right);
if (data1 == null && data2 == null) return null;
if (data1 == null || data2 == null) {
Data<T> dataTemp = data1 != null ? data1 : data2;
dataTemp.count++;
return dataTemp;
}
if (data1.count >= data2.count) {
data1.count++;
return data1;
} else {
data2.count++;
return data2;
}
}
}
public class DeepestLeftLeafTest {
@Test
public void test1() {
DeepestLeftLeaf<Integer> deepestLL1 = new DeepestLeftLeaf<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8));
assertEquals(8, (int)deepestLL1.leftNode());
}
@Test
public void test2() {
DeepestLeftLeaf<Integer> deepestLL2 = new DeepestLeftLeaf<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7));
assertEquals(4, (int)deepestLL2.leftNode());
}
@Test
public void test3() {
DeepestLeftLeaf<Integer> deepestLL3 = new DeepestLeftLeaf<Integer>(Arrays.asList(1, 2, 3, null, 5, 6, 7));
assertEquals(6, (int)deepestLL3.leftNode());
}
@Test
public void test4() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, null, 5, 6, null, null, null, null, null, 7, null, 8, null,
null, null, null, null, null, null, null, null, null, 9, null, null, null, null, 10);
DeepestLeftLeaf<Integer> deepestLL4 = new DeepestLeftLeaf<Integer>(list);
assertEquals(9, (int) deepestLL4.leftNode());
}
}