Leetcode114. Flatten Binary Tree to Linked List

Leetcode114. Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.
For example, given the following tree:

    1
   / \
  2   5
 / \   \
3   4   6

The flattened tree should look like:

1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6

Solution one

    1
   / \
  2   5
 / \   \
3   4   6

//Insert the left subtree of 1 into the right subtree
    1
     \
      2         5
     / \         \
    3   4         6        
//Connect the original right subtree to the rightmost node of the left subtree
    1
     \
      2          
     / \          
    3   4  
         \
          5
           \
            6

 //Insert the left subtree of 2 into the right subtree
    1
     \
      2          
       \          
        3       4  
                 \
                  5
                   \
                    6   

 //Connect the original right subtree to the rightmost node of the left subtree
    1
     \
      2          
       \          
        3      
         \
          4  
           \
            5
             \
              6         

  ......
public void flatten(TreeNode root) {
    while (root != null) { 
        //The left subtree is null, and the next node is directly considered
        if (root.left == null) {
            root = root.right;
        } else {
            // Find the rightmost node of the left subtree
            TreeNode pre = root.left;
            while (pre.right != null) {
                pre = pre.right;
            } 
            //Connect the original right subtree to the rightmost node of the left subtree
            pre.right = root.right;
            // Insert the left subtree into the right subtree
            root.right = root.left;
            root.left = null;   //Leave the left subtree empty!
            // Consider next node
            root = root.right;
        }
    }
}

Solution to the post order order of two deformations

The basic idea is to change the direction directly on the original node

The meaning of the question is to form a linked list by passing a binary tree through the right pointer. 1 -> 2 -> 3 -> 4 -> 5 -> 6

We know that the traversal order given by the topic is actually the order of the first order traversal, so can we use the code of the first order traversal to update the right pointer of the previous node to the current node every time we traverse a node.

The first order of traversal is 1 23 4 5 6.
Traverse to 2 and point the right pointer of 1 to 2. 1 -> 2 3 4 5 6. 
Traverse to 3 and point the right pointer of 2 to 3. 1 -> 2 -> 3 4 5 6. 
... ...

The problem is that if we point the right pointer of 1 to 2, then the original right child of 1 will be lost, that is, 5 will not be found.

The solution is that we can go backwards.

Traverse 654321 in turn, then update the right pointer of the current node to the previous node for each node traversed.
Traverse to 5 and point the right pointer of 5 to 6. 6 <- 5 4 3 2 1. 
Traverse to 4 and point the right pointer of 4 to 5. 6 <- 5 <- 4 3 2 1. 
... ...

In this way, there will be no problem of losing children, because when the current right pointer is updated, the right child of the current node has been accessed.

However, the traversal order of 654321 is actually the post order traversal, which is right subtree - > left subtree - > root node.

The code of deformed post order traversal

public void postorder(TreeNode<T> root){
    if (root == null)
        return;
    postorder(root.right);
    postorder(root.left); 
    System.out.print(root.data);

}

Instead of printing the root node, we use a global variable pre to update the right pointer of the current root node to pre and the left pointer to null.

private TreeNode pre = null;

public void flatten(TreeNode root) {
    if (root == null)
        return;
    flatten(root.right);
    flatten(root.left);
    root.right = pre;
    root.left = null;
    pre = root;
}

The corresponding left child should also be set to null. Similarly, there is no need to worry about the loss of the left child, because it is a post order traversal, and the left child has already traversed.

Iteration form:

public void flatten(TreeNode root) { 
    Stack<TreeNode> toVisit = new Stack<>();
    TreeNode cur = root;
    TreeNode pre = null;

    while (cur != null || !toVisit.isEmpty()) {
        while (cur != null) {
            toVisit.push(cur); // Add root node
            cur = cur.right; // Add right node recursively
        }
        cur = toVisit.peek(); // The rightmost node has been accessed
        // Access the root node when there is no left node or the right node has already accessed it
        if (cur.left == null || cur.left == pre) {
            toVisit.pop(); 
            /**************Where to modify***************/
            cur.right = pre;
            cur.left = null;
            /*************************************/
            pre = cur;
            cur = null;
        } else {
            cur = cur.left; // Access the left node before it has been accessed
        }
    } 
}

Solution three

Published 64 original articles, won praise 3, visited 3768
Private letter follow

Posted by slurpee on Thu, 13 Feb 2020 05:27:53 -0800