Diameter of a Binary Tree

Problem

The tree is given in level order on one line, with null for a missing child. The diameter is the number of edges on the longest path between any two nodes (the path does not have to go through the root). Print the diameter.

Constraints

  • 1 <= n <= 10^4 nodes

Examples

Input

1 2 3 4 5

Output

3

Solutions

Best approachTime O(n)Space O(h)

The longest path has a top node, where it bends. Its length is the depth of the left side plus the depth of the right side. One recursion returns the depth and also records the best bend, so the whole tree is visited once.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Process a binary tree.
 * Input   : One line: the tree in level order, null for a missing child.
 * Output  : The diameter.
 * Approach: One pass with depth.
 * Time    : O(n)
 * Space   : O(h)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: A tree node has a value and links to the left and right child. null means: no child.
        static class TreeNode {
            int value;
            TreeNode left;
            TreeNode right;

            TreeNode(int value) {
                this.value = value;
            }
        }

        // This method builds a tree from the level order tokens. A queue keeps the nodes that still need children.
        static TreeNode build(String[] tokens) {
            if (tokens.length == 0 || tokens[0].equals("null")) {
                return null;
            }
            TreeNode root = new TreeNode(Integer.parseInt(tokens[0]));
            java.util.ArrayDeque<TreeNode> queue = new java.util.ArrayDeque<>();
            queue.add(root);
            int i = 1;
            while (!queue.isEmpty() && i < tokens.length) {
                TreeNode node = queue.poll();
                if (i < tokens.length && !tokens[i].equals("null")) {
                    node.left = new TreeNode(Integer.parseInt(tokens[i]));
                    queue.add(node.left);
                }
                i++;
                if (i < tokens.length && !tokens[i].equals("null")) {
                    node.right = new TreeNode(Integer.parseInt(tokens[i]));
                    queue.add(node.right);
                }
                i++;
            }
            return root;
        }

        // Step 2: A path that bends at a node goes down the left side and down the right side.
        static int depth(TreeNode node, int[] best) {
            if (node == null) {
                return 0;
            }
            int left = depth(node.left, best);
            int right = depth(node.right, best);
            // Step 3: Its length in edges is left + right. The node reports its own depth to its parent.
            best[0] = Math.max(best[0], left + right);
            return 1 + Math.max(left, right);
        }

    // This method solves the task. It receives the input and returns the answer.
    static long solve(String s) {
        // Step 4: One pass: each node reports its depth, and updates the best path that bends at this node.
        int[] best = new int[1];
        depth(build(s.trim().split(" ")), best);
        return best[0];
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.hasNextLine() ? scanner.nextLine() : "";
        System.out.println(solve(s));
    }
}
Hints (2)
  1. Where does the longest path bend?
  2. What does each call return?