16

Recursive mechanism to find max depth of depth of binary tree is very straightforward, but how can we do it efficiently without recursion as I have large tree where I would rather avoid this recursion.

//Recursive mechanism which I want to replace with non-recursive
private static int maxDepth(Node node) {
if (node == null) return 0;
    return 1 + Math.max(maxDepth(node.left), maxDepth(node.right)); 
}

PS: I am looking for answers in Java.

7 Answers 7

18

This variant uses two stacks, one for additional nodes to explore (wq) and one always containing the current path from the root (path). When we see the same node on the top of both stacks it means we've explored everything below it and can pop it. This is the time to update the tree depth too. On random or balanced trees the additional space should be O(log n), in the worst case O(n), of course.

static int maxDepth (Node r) {
    int depth = 0;
    Stack<Node> wq = new Stack<>();
    Stack<Node> path = new Stack<>();

    wq.push (r);
    while (!wq.empty()) {
        r = wq.peek();
        if (!path.empty() && r == path.peek()) {
            if (path.size() > depth)
                depth = path.size();
            path.pop();
            wq.pop();
        } else {
            path.push(r);
            if (r.right != null)
                wq.push(r.right);
            if (r.left != null)
                wq.push(r.left);
        }
    }

    return depth;
}

(Shameless plug: I had this idea for using dual stacks for non-recursive traversals a few weeks ago, check for a C++ code here http://momchil-velikov.blogspot.com/2013/10/non-recursive-tree-traversal.html not that I claim I was the first to invent it :)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks - I have accepted your answer, as it is not keeping list of nodes traveled which added space complexity.
An implementation note: it's better to use ArrayDeque instead of Stack in Java: the Stack class is unnecessarily synchronized.
2

The recursive approach you've described is essentially a DFS over the binary tree. You can implement this iteratively if you'd like by storing an explicit stack of nodes and keeping track of the maximum depth encountered.

Hope this helps!

2 Comments

Can you provide any sample? Is this efficient way? As I don't want to increase space complexity.
@Hemant- Iterative and recursive DFS's have the same time and space complexities, though the recursive version typically uses stack space while the iterative version uses heap space. Search for "iterative DFS" for some good pseudocode to use as a starting point.
2

I have written following logic to do find max and min depth which doesn't involve recursion and without increasing the space complexity.

// Find the maximum depth in the tree without using recursion
private static int maxDepthNoRecursion(TreeNode root) {
    return Math.max(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
}

// Find the minimum depth in the tree without using recursion
private static int minDepthNoRecursion(TreeNode root) {
    return Math.min(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
}

private static int maxDepthNoRecursion(TreeNode root, boolean left) {
    Stack<TreeNode> stack = new Stack<>();
    stack.add(root);
    int depth = 0;
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        if (left && node.left != null) stack.add(node.left);
        // Add the right node only if the left node is empty to find max depth
        if (left && node.left == null && node.right != null) stack.add(node.right); 
        if (!left && node.right != null) stack.add(node.right);
        // Add the left node only if the right node is empty to find max depth
        if (!left && node.right == null && node.left != null) stack.add(node.left);
        depth++;
    }
    return depth;
}

5 Comments

You don't really need to keep track of visited nodes, because in a tree there's a single path from the root to any other node.
@chill - Not keeping track of visited nodes causes recursion, even though tree doesn't have any circular reference.
oh, you mean with your particular algorithm? OK. See my answer for a variant with expected O(log n) additional space complexity.
The algorithm does not appear to work for certain formations of the tree. It is returning max depth of 3 for the below tree (expected 4). node1.left=node2; node1.right=node3; node2.left=node4; node2.right=node5; node3.left=node6; node3.right=node7; node5.right=node8; node6.left=node9;
totally wrong algorithm it will be considered only if the max depth on the left of the left node of the roor or on the right of the right node of the root of the tree . try this and it will fail tree2.Insert(30); tree2.Insert(10); tree2.Insert(50); tree2.Insert(5); tree2.Insert(11); tree2.Insert(12); tree2.Insert(13); tree2.Insert(14);
2

Another way is to use Level order traversal, where tree height is equal to the number of level of a tree. (It can only be use to calulate the minimal height of a tree.)

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    LinkedList<TreeNode> arr = new LinkedList<TreeNode>(); // queue for current level
    LinkedList<TreeNode> tmp = new LinkedList<TreeNode>(); // queue for next level
    arr.add(root);
    int res = 0; // result
    TreeNode node; // tmp node 
    while (true) {
        while (!arr.isEmpty()) {
            node = arr.poll();
            if (node.left != null) tmp.add(node.left);
            if (node.right != null) tmp.add(node.right);
        }
        res++;
        if (tmp.isEmpty()) break;
        arr = tmp;
        tmp = new LinkedList<TreeNode>();
    }
    return res;
}

Comments

0

If you can maintain left and right values at each node, it can be done.

http://leetcode.com/2010/04/maximum-height-of-binary-tree.html.

Possible duplicate: Retrieving a Binary-Tree node's depth non-recursively

Comments

0

Using a Array to store a layer of nodes, each time find a new layer. the depth plus one.

public int maxDepth2(TreeNode root){
        if(root == null){
            return 0;
        }

        int depth = 0;

        ArrayList<TreeNode> oneLayer = new ArrayList<TreeNode>();
        oneLayer.add(root);

        while(!oneLayer.isEmpty()){
            ArrayList<TreeNode> newLayer = new ArrayList<TreeNode>();
            for(TreeNode node:oneLayer){
                if(node.right!=null){
                    newLayer.add(node.right);
                }
                if(node.left!=null){
                    newLayer.add(node.left);
                }
            }
            oneLayer = newLayer;
            depth++;
        }

        return depth;
    }

Comments

0

Here is a BFS solution:

private class NodeHeight
{
    public Node node;
    public int height;

    public NodeHeight(Node n, int height)
    {
        node = n;
        this.height = height;
    }
}

public int GetHeightBfs(Node root)
{
    if(root == null)
        return 0;
    else
        return GetHeightBfs(new NodeHeight(root, 1))
}

private int GetHeightBfs(NodeHeight root)
{   
    int maxHeight = int.Min;
    int minHeight = int.Max;
    var q = new Queue<Node>();
    q.Enqueue(root);
    while(q.length > 0)
    {       
        var nodeHeight = q.Dequeue();
        var node = nodeHeight.node;
        int height = nodeHeight.height;
        if(node.left == null && node.right == null)
        {
            maxHeight = Math.max(maxHeight, height);
            minHeight = Math.min(minHeight, height);
        }

        if(node.left != null)
            q.Enqueue(new NodeHeight(node.left, height + 1);

        if(node.right != null)
            q.Enqueue(new NodeHeight(node.right, height + 1);
    }

    return maxHeight;
}   

Note that you can also return minHeight. To make it DFS just replace Queue with Stack.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.