[Daily Coding Problem 223] O space in order traversal of a binary tree

Posted lz87

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Daily Coding Problem 223] O space in order traversal of a binary tree相关的知识,希望对你有一定的参考价值。

Typically, an implementation of in-order traversal of a binary tree has O(h) space complexity, where h is the height of the tree. Write a program to compute the in-order traversal of a binary tree using O(1) space.

 

In-order traversal without recursion with O(h) space, where h is the tree‘s height.

 

public List<Integer> inOrderTraversal(BinaryTreeNode root) 
    List<Integer> vals = new ArrayList<>();
    if(root == null) 
        return vals;
    
    Stack<BinaryTreeNode> stack = new Stack<>();
    BinaryTreeNode curr = root;

    while(stack.size() > 0 || curr != null) 
        while(curr != null) 
            stack.push(curr);
            curr = curr.getLeft();
        
        curr = stack.pop();
        vals.add(curr.getVal());
        curr = curr.getRight();
    
    return vals;

 

O(1) space solution

The reason that the stack solution requires O(h) space consumption is because we must have some way to traverse back to a current node after traversing its left subtree. To avoid this space consumption, we need to restructure the tree while we traverse it, so that going to the right will always go to the "correct" next node. Namely, right after visiting the rightmost node in a left subtree, we continue to visit this rightmost node‘s right child that will lead us back to the this left subtree‘s parent. 

 

Take the binary tree below as an example. Starting from root 8, it has a left subtree. Before traversing its left subtree, we need to get the rightmost descendant of this subtree and set its right child to be the root node 8. Otherwise, we wouldn‘t have any way of coming back to root. So we set 7‘s right child to be 8. After this step, traverse the left subtree. For node 3, we do the same, setting 1‘s right child to be 3. Repeat this until a node has no left subtree. At this point, we know we need to add its value to the result list. In an in-order traversal, we visit a node‘s right child after visiting the node. So we go back to 3. Now here comes a problem. Since we are constrained with constant space, we do not know that 3‘s left subtree has been traversed. How do we check that this is the case? We apply the same logic here: trying to the rightmost descendant of 3‘s left child(1) points to 3. After finding out that 1‘s right child already points to 3, we know that we have already traversed the left subtree with a root node 1. At this point, we need to revert the changes made to node 1 by setting its right child back to null. Then add 3 to the result list and traverse 3‘s right subtree. 

 

Algorithm:

1. if the current node has no left subtree, visit it;

2. if it has left subtree, make the rightmost descendant node‘s right child in its left subtree points to itself; 

2(a). If this is already done before, revert the changes, visit the current node, then traverse its right subtree;

2(b). If this has not been done, do the upate, then traverse the current node‘s left subtree;

3. Repeat steps 1 and 2 until the current node becomes null.

 

This approach uses O(1) space at the cost of slower runtime as we need to traverse each left subtrees of every node twice.

public List<Integer> inOrderTraversalConstantSpace(BinaryTreeNode root) 
    List<Integer> vals = new ArrayList<>();
    BinaryTreeNode curr = root;

    while(curr != null) 
        //add val if there is no left node to go to
        if(curr.getLeft() == null) 
            vals.add(curr.getVal());
            curr = curr.getRight();
        
        //make the rightmost descendant of curr‘s left child points to curr
        else 
            BinaryTreeNode rightMostDesc = curr.getLeft();
            while(rightMostDesc.getRight() != null && rightMostDesc.getRight() != curr) 
                rightMostDesc = rightMostDesc.getRight();
            
            if(rightMostDesc.getRight() == null) 
                rightMostDesc.setRight(curr);
                curr = curr.getLeft();
            
            else 
                rightMostDesc.setRight(null);
                vals.add(curr.getVal());
                curr = curr.getRight();
            
        
    
    return vals;

 

 

 

 

技术图片

 

This problem basically implements a single threaded binary tree. For more references on this, refer to Threaded Binary Tree: https://www.geeksforgeeks.org/threaded-binary-tree/

 

以上是关于[Daily Coding Problem 223] O space in order traversal of a binary tree的主要内容,如果未能解决你的问题,请参考以下文章

Daily Coding Problem: Problem #339

[Daily Coding Problem 290] Quxes Transformation

[Daily Coding Problem 250] Cryptarithmetic Puzzle

[Daily Coding Problem 70] Nth perfect number

[Daily Coding Problem 68] Count Pairs of attacking bishop pairs

[Daily Coding Problem 24] Implement locking in a binary tree.