[Daily Coding Problem 223] O(1) 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/

原文地址:https://www.cnblogs.com/lz87/p/11162989.html

时间: 2024-08-29 10:16:00

[Daily Coding Problem 223] O(1) space in order traversal of a binary tree的相关文章

[Daily Coding Problem 294] Shortest round route with rising then falling elevations

A competitive runner would like to create a route that starts and ends at his house, with the condition that the route goes entirely uphill at first, and then entirely downhill. Given a dictionary of places of the form {location: elevation}, and a di

[Daily Coding Problem] 1 (LeetCode 1). Find if two numbers in an array add up to k

This problem was recently asked by Google. Given a list of numbers and a number k, return whether any two numbers from the list add up to k. For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17. Bonus: Can you do this in one

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

This problem was asked by Google. On our special chessboard, two bishops attack each other if they share the same diagonal. This includes bishops that have another bishop located between them, i.e. bishops can attack through pieces. You are given N b

[Daily Coding Problem 70] Nth perfect number

This problem was asked by Microsoft. A number is considered perfect if its digits sum up to exactly 10. Given a positive integer n, return the n-th perfect number. For example, given 1, you should return 19. Given 2, you should return 28. This is one

Daily Coding Problem: Problem #315

/** * This problem was asked by Google. In linear algebra, a Toeplitz matrix is one in which the elements on any given diagonal from top left to bottom right are identical. Here is an example: 1 2 3 4 8 5 1 2 3 4 4 5 1 2 3 7 4 5 1 2 Write a program t

Daily Coding Problem: Problem #339

/** * This problem was asked by Microsoft. Given an array of numbers and a number k, determine if there are three entries in the array which add up to the specified number k. For example, given [20, 303, 3, 4, 25] and k = 49, return true as 20 + 4 +

[Daily Coding Problem 250] Cryptarithmetic Puzzle

A cryptarithmetic puzzle is a mathematical game where the digits of some numbers are represented by letters. Each letter represents a unique digit. For example, a puzzle of the form: SEND + MORE -------- MONEY may have the solution: {'S': 9, 'E': 5,

[Daily Coding Problem 290] Quxes Transformation

On a mysterious island there are creatures known as Quxes which come in three colors: red, green, and blue. One power of the Qux is that if two of them are standing next to each other, they can transform into a single creature of the third color. Giv

[Daily Coding Problem] Find the total number of solutions of a linear equation of n variables

Given a linear equation of n variables, find the total number of non-negative integer solutions of it. All coefficients are positive. Example: input: x + 2 * y = 5 output: 3,  the 3 possible integer solutions are x = 1, y = 2; x = 3, y = 1; x = 5, y