Check if all leaves are at same level Check if all leaves are at same level. This question is attributed to geek for geeks. Looking for code-review, optimization and best practices.

public class LeavesLevel&lt;T&gt; {

    private TreeNode&lt;T&gt; root;

    public LeavesLevel(List&lt;T&gt; items) {
        create (items);
    }

    private void create (List&lt;T&gt; items) {        
        root = new TreeNode&lt;&gt;(items.get(0));

        final Queue&lt;TreeNode&lt;T&gt;&gt; queue = new LinkedList&lt;TreeNode&lt;T&gt;&gt;();
        queue.add(root);

        final int half = items.size() / 2;

        for (int i = 0; i &lt; half; i++) {
            if (items.get(i) != null) {
                final TreeNode&lt;T&gt; current = queue.poll();
                final int left = 2 * i + 1;
                final int right = 2 * i + 2;

                if (items.get(left) != null) {
                    current.left = new TreeNode&lt;T&gt;(items.get(left));
                    queue.add(current.left);
                }
                if (right &lt; items.size() &amp;&amp; items.get(right) != null) {
                    current.right = new TreeNode&lt;T&gt;(items.get(right));
                    queue.add(current.right);
                }
            }
        }
    }


    private static class TreeNode&lt;T&gt; {
        private TreeNode&lt;T&gt; left;
        private T item;
        private TreeNode&lt;T&gt; right;

        TreeNode(T item) {
            this.item = item;
        }
    }

    public boolean refurbish() {
        return recurse (root, 0,  new NodeDepth(-1));
    }

    private static class NodeDepth {
        private int depth;
        NodeDepth(int depth) {
            this.depth = depth;
        }
    }

    public boolean recurse(TreeNode&lt;T&gt; node, int leafLevel, NodeDepth nodeDepth) {
        if (node == null) {
            return true;
        }

        if (node.left == null &amp;&amp; node.right == null) {
           if (nodeDepth.depth == -1) {
               nodeDepth.depth = leafLevel;
               return true; // if tree contains a single leaf node, then 
           }
           return leafLevel == nodeDepth.depth;
        }

        return recurse (node.left, leafLevel + 1, nodeDepth) &amp;&amp; recurse (node.right, leafLevel + 1, nodeDepth);
    }
}


public class LeafLevelTest {

    @Test
    public void test1() {
        /**
         * 
         *           12
                   /    \
                 5       7       
               /          \ 
              3             1
         * 
         */
        LeavesLevel&lt;Integer&gt; ll1 = new LeavesLevel&lt;&gt;(Arrays.asList(1, 5, 7, 3, null, null, 1)); 
        assertTrue(ll1.refurbish());
    }

    @Test
    public void test2() {
        /**
         *       12
                /    \
              5       7       
             /          
            3          
         * 
         */
        LeavesLevel&lt;Integer&gt; ll2 = new LeavesLevel&lt;&gt;(Arrays.asList(1, 5, 7, 3)); 
        assertFalse(ll2.refurbish());
    }

    @Test
    public void test3() {
        /**
         * 
         * 
                    12
                    /    
                  5             
                /   \        
               3     9
              /      /
             1      2
         * 
         * 
         */
        LeavesLevel&lt;Integer&gt; ll3 = new LeavesLevel&lt;&gt;(Arrays.asList(1, 5, null, 3, 9, null, null, 1, null, 2)); 
        assertTrue(ll3.refurbish());
    }

}
Code reuse

You've asked a few dozen questions about tree algorithms, many of which contain very similar code.  Copy-and-paste programming is an antipattern; copy-and-pasting with modifications here and there is even worse.  By now, you should have developed a library of reusable classes.

That means decomposing your classes to obey the Single Responsibility Principle.  There should be a TreeNode&lt;T&gt; class that acts as a generic node with two child pointers, and possibly a create(List&lt;? extends T&gt;) convenience method.

public class TreeNode&lt;T&gt; {
    public TreeNode&lt;T&gt; left, right;
    public final T item;

    public TreeNode(T item) {
        this.item = item;
    }

    public static &lt;T&gt; TreeNode&lt;T&gt; createTree(List&lt;? extends T&gt; items) {
        TreeNode&lt;T&gt; root = new TreeNode&lt;&gt;(items.get(0));

        final Queue&lt;TreeNode&lt;T&gt;&gt; queue = new LinkedList&lt;TreeNode&lt;T&gt;&gt;();
        queue.add(root);

        final int half = items.size() / 2;

        for (int i = 0; i &lt; half; i++) {
            if (items.get(i) != null) {
                final TreeNode&lt;T&gt; current = queue.poll();
                final int left = 2 * i + 1;
                final int right = 2 * i + 2;

                if (items.get(left) != null) {
                    current.left = new TreeNode&lt;T&gt;(items.get(left));
                    queue.add(current.left);
                }
                if (right &lt; items.size() &amp;&amp; items.get(right) != null) {
                    current.right = new TreeNode&lt;T&gt;(items.get(right));
                    queue.add(current.right);
                }
            }
        }
        return root;
    }
}


There should be a TreePredicate&lt;T&gt; interface for algorithms that test a tree and return a true/false result.

interface TreePredicate&lt;T&gt; {
    boolean test(TreeNode&lt;T&gt; root);
}


Algorithms that implement the TreePredicate&lt;T&gt; interface should be in classes that are named as nouns, as with all Java classes.

Algorithm

Your use of recursion is weird.

The methods are poorly named: refurbish() is unintuitive; recurse() is too generic.  Furthermore, recurse() looks like a helper function that should not have been made public.

You shouldn't use mutation with recursion.  A key advantage of recursion is that immutable stack values make it easy to extend local reasoning to the large scale.  Impure functions with side-effects make such analysis difficult.

It should be clear what the invariants are when you recurse.  See the example JavaDoc below.

public class UniformLeafDepthPredicate&lt;T&gt; implements TreePredicate&lt;T&gt; {

    public boolean test(TreeNode&lt;T&gt; root) {
        return allLeavesDepth(root) &gt;= 0;
    }   

    /**
     * Returns the depth of this node, if the paths to all of its descendant
     * leaf nodes are all of the same length, or -1 if the height is
     * non-uniform.  The depth of a leaf node is 1.
     */
    private int allLeavesDepth(TreeNode&lt;T&gt; node) {
        if (node == null) return 0;

        int lDepth = allLeavesDepth(node.left);
        if (lDepth &lt; 0) return -1;          // LHS has non-uniform depth
        int rDepth = allLeavesDepth(node.right);
        if (rDepth &lt; 0) return -1;          // RHS has non-uniform depth

        if (lDepth == 0) return 1 + rDepth; // Only R child; RHS has uniform depth
        if (rDepth == 0) return 1 + lDepth; // Only L child; LHS has uniform depth

        return (lDepth == rDepth) ? 1 + lDepth : -1;
    }   
}


By following these guidelines for recursion, the code is greatly simplified.

Unit tests

I don't know why you labelled the root node as "12" in your comments.  It's inconsistent with your actual tests.

I suggest adding one more test, because you currently have no test in which a child node has non-uniform depth.

public class LeafLevelTest {

    private TreePredicate&lt;Integer&gt; tester = new UniformLeafDepthPredicate&lt;&gt;();

    …

    @Test
    public void test4() {
        /*
                   1
                  /
                 5
                / \
               3   9
              /
             4
         */
        TreeNode&lt;Integer&gt; ll4 = TreeNode.createTree(Arrays.asList(1, 5, null, 3, 9, null, null, 4));
        assertFalse(tester.test(ll4));
    }
}