LeetCode brush questions - I can flip the binary tree. Does Google want me?

Preface description

Algorithm learning, daily problem brushing records.

Topic connection

Flip binary tree

Topic content

Flip a binary tree.

Example:

Input:

Output:

remarks:

This question is inspired by Max Howell's original question:

Google: 90% of our engineers use the software you wrote (Homebrew), but you can't write the question of flipping binary tree on the whiteboard during the interview, which is too bad.

Analysis process

Flipping a binary tree is very simple. You can use recursion.

The binary tree is regarded as the whole of the root node, left child and right child, and the left child and right child of the root node are flipped as a whole.

If the left child and the right child are also trees, the same method is executed recursively until the left child and the right child are empty.

Finally, the root node of the binary tree is returned, which is the inverted binary tree.

Answer code

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            // If the tree node is empty, it returns null directly
            return null;
        }

        // Using the recursive method, the tree is regarded as the whole of the root node, the left child and the right child, and the left child and the right child of the root node are flipped as a whole. If the left child and the right child are also trees, the same method is executed recursively until the left child and the right child are empty, and the recursion starts backtracking

        // Gets the left child of the root node
        TreeNode left = invertTree(root.left);

        // The left child of the root node is equal to the right child, and the right child is equal to the left child. Flip is realized
        root.left = invertTree(root.right);
        root.right = left;

        // Returns the flipped root node
        return root;
    }
}

Submit results

The execution time is 0ms, the time beats 100.00% of users, the memory consumption is 35.9MB, and the space beats 37.33% of users.

The original flip binary tree is so simple that I will flip the binary tree. Does Google want me?

Extension analysis

However, I will write the complete code when I brush the questions. Obviously, the above code is not complete. When we execute and run, we input an array and output an array, as shown in the figure:

The invertTree method actually inputs a binary tree TreeNode object, so there is actually an input process of converting an array into a binary tree and an output process of converting a binary tree back to an array. When you brush questions on LeetCode, the LeetCode background has done the conversion for you, but if we want to write the complete code ourselves, we need to do the conversion ourselves.

Here, only one array is given to determine the binary tree, which is proved to be sequence traversal, because pre sequence traversal, middle sequence traversal and post sequence traversal cannot deduce the binary tree from a single array, and sequence traversal can deduce the binary tree from a single array.

Sequence traversal: access all nodes layer by layer from top to bottom, and each layer from left to right.

To facilitate understanding, the following examples are given:

Input array 1: [0,null,2,null,4,null,6]

Output binary tree 1:

Input array 2: [1,null,2,3]

Output binary tree 2:

Input array 3: [0,1,null,null,4]

Output binary tree 3:

Input array 4: [4,2,7,1,3,6,9]

Output binary tree 4:

Array to binary tree: it's a little strange that I have read many algorithm books and consulted many online materials. I rarely see how to turn the sequence traversed array into a binary tree. Next, I have sorted out a conversion method. Please see the complete code arrayToTreeNode method behind to realize breadth first search through queue assistance, That is, simulate the process of sequence traversal from top to bottom and from left to right, and convert the array into a binary tree. Pay attention to the case that the array element is null. When the array element is null, the node has no children, but it will occupy an array element.

Binary tree to array: see the following complete code treenodotoarray method, which also realizes breadth first search through queue assistance, that is, simulate the process from top to bottom and from left to right during sequence traversal, first convert the binary tree into a two-layer List, each layer of the two-layer List saves the node values from left to right of one layer of tree, and finally convert the two-layer List into an array, Here, you should also pay attention to the case that the array elements are null. If all the elements in a row are null, do not use this row; If last element in a row is null, remove last element.

The complete code is as follows:

import java.util.*;

public class Main {

    public static void main(String[] args) {
        // Get input results
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        scanner.close();

        // Process input results
        Integer[] nums;
        if ("[]".equals(str)) {
            // When the array is empty
            nums = null;
        } else {
            // When the array is not empty
            String[] strs = str.split("\\[")[1].split("]")[0].split(",");
            int size = strs.length;
            nums = new Integer[size];
            for (int i = 0; i < size; ++i) {
                if ("null".equals(strs[i])) {
                    nums[i] = null;
                } else {
                    nums[i] = Integer.parseInt(strs[i]);
                }
            }
        }

        // Convert array to binary tree
        TreeNode root = arrayToTreeNode(nums);

        // Get output results
        TreeNode result = invertTree(root);
        System.out.println(Arrays.toString(treeNodeToArray(result)));
    }

    // The array is transformed into a binary tree, the sequence is traversed, and the layers are in the order from top to bottom and from left to right
    private static TreeNode arrayToTreeNode(Integer[] nums) {
        // Using queue assistance, you should pay special attention to supporting null array elements. When the array element is null, the node has no children, but it will occupy an array element
        // If the left child of the node is null and the right child is not null, the next element of the array will start from the child node of the right child, because the left child is null and has no child node
        // Examples: [0,null,2,null,4,null,6], [1,null,2,3], [0,1,null,null,4], [4,2,7,1,3,6,9]

        if (nums == null || nums.length == 0) {
            // If the binary tree node is empty, it returns null directly
            return null;
        }

        // Start subscript of array
        int i = 1;

        // First, construct the root node of binary tree
        TreeNode root = new TreeNode(nums[0]);

        // Define the current binary tree node and save the temporary value
        TreeNode current;

        // Defines the value of the current array
        Integer value;

        // Define the queue and create a binary tree
        Queue<TreeNode> queue = new LinkedList<>();

        // First put the root node of the binary tree into the queue, and finally
        queue.add(root);

        // Traverse the array and construct a binary tree
        while (i < nums.length) {
            // Queue out the first element and get the current binary tree node
            current = queue.poll();

            // Gets the value of the array, with the array subscript plus 1
            value = nums[i++];

            if (value != null) {
                // Creates the left child of the current binary tree node
                TreeNode left = new TreeNode(value);

                if (current != null) {
                    // Construct the left child of the current binary tree node
                    current.left = left;
                }

                // Put the left child of the current binary tree node at the end of the queue
                queue.add(left);
            }

            if (i < nums.length) {
                // Gets the value of the array, with the array subscript plus 1
                value = nums[i++];

                if (value != null) {
                    // Creates the right child of the current binary tree node
                    TreeNode right = new TreeNode(value);

                    if (current != null) {
                        // Construct the right child of the current binary tree node
                        current.right = right;
                    }

                    // Put the right child of the current binary tree node at the end of the queue
                    queue.add(right);
                }
            }
        }

        // Returns the root node of the binary tree
        return root;
    }

    // The binary tree is converted into an array, the sequence is traversed, and the layers are in the order from top to bottom and from left to right. Here, because the binary tree is flipped, special treatment is required. The empty nodes in the last layer should also be displayed and displayed as null, so as to see the effect of the flipped binary tree
    private static Integer[] treeNodeToArray(TreeNode root) {
        // Define a two-tier list and save the overall results
        List<List<Integer>> list = new ArrayList<>();

        if (root == null) {
            // If the binary tree node is empty, an empty array is returned directly
            return new Integer[0];
        }

        // Through queue assistance, the traversal of each layer is completed from top to bottom. When traversing each layer, each node is traversed, the two child nodes of the node are determined. If it is not empty, the child nodes are placed behind the queue. The queue ensures that the tree traverses from top to bottom according to the hierarchy and each layer traverses from left to right

        // Define queue
        Queue<TreeNode> queue = new LinkedList<>();

        // First put the root node of the binary tree into the queue, and finally
        queue.add(root);

        // Loop until the length of the queue is zero, ending the loop
        while (queue.size() > 0) {
            // Define the inner layer list and save the inner layer results
            List<Integer> temp = new ArrayList<>();

            // Gets the length of the queue
            int size = queue.size();

            // Traverse the queue and complete the traversal of one layer of tree nodes each time
            for (int i = 0; i < size; ++i) {
                // Queue out first element
                TreeNode node = queue.poll();

                if (node != null) {
                    // Add the value of the listed element to the inner list
                    temp.add(node.val);

                    if (node.left != null) {
                        // Put the left child of the current binary tree node at the end of the queue
                        queue.add(node.left);
                    } else {
                        // If the child node is empty, it should also be put into the queue. Finally, in order to adapt to the effect of flipping the binary tree
                        queue.add(null);
                    }

                    if (node.right != null) {
                        // Put the right child of the current binary tree node at the end of the queue
                        queue.add(node.right);
                    } else {
                        // If the child node is empty, it should also be put into the queue. Finally, in order to adapt to the effect of flipping the binary tree
                        queue.add(null);
                    }
                } else {
                    // The null value is added to the inner list to adapt to the effect of flipping the binary tree
                    temp.add(null);
                }
            }

            // Are all elements of the inner list empty
            boolean isAllNull = true;

            // Judge whether all the elements of the inner list are empty. If all the elements are empty, there is more inner list data in this row
            for (Integer col : temp) {
                if (col != null) {
                    // As long as one element is not empty, not all elements are empty
                    isAllNull = false;
                    break;
                }
            }

            if (!isAllNull) {
                // Not all elements are empty inner lists before they are added to the two-tier list
                list.add(temp);
            }
        }

        // Print sequence traversal results in two-layer list form
        System.out.println("treeNodeToArray list:" + list);

        // Defines the length of the array
        int count = 0;

        // Traverse the two-tier list and calculate the length of the array
        for (List<Integer> row : list) {
            // The length of each row list is accumulated
            count += row.size();
        }

        // Define array
        Integer[] nums = new Integer[count];

        // Defines the subscript of the array
        int n = 0;

        // Traverse the two-tier list and turn the two-tier list into an array
        for (List<Integer> row : list) {
            for (Integer col : row) {
                nums[n++] = col;
            }
        }

        if (nums[nums.length - 1] == null) {
            // If the last element is null, delete the last element. In this case, null must fall on the right node, and the last position. If the last element is null, do not keep it. If NULL is on the left, it should be kept
            return Arrays.copyOf(nums, nums.length - 1);
        }

        // Return array
        return nums;
    }

    // Flip binary tree
    private static TreeNode invertTree(TreeNode root) {
        if (root == null) {
            // If the tree node is empty, it returns null directly
            return null;
        }

        // Using the recursive method, the tree is regarded as the whole of the root node, the left child and the right child, and the left child and the right child of the root node are flipped as a whole. If the left child and the right child are also trees, the same method is executed recursively until the left child and the right child are empty, and the recursion starts backtracking

        // Gets the left child of the root node
        TreeNode left = invertTree(root.left);

        // The left child of the root node is equal to the right child, and the right child is equal to the left child. Flip is realized
        root.left = invertTree(root.right);
        root.right = left;

        // Returns the flipped root node
        return root;
    }

}

// Define binary tree
class TreeNode {

    int val;

    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

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

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

}

Complete code acquisition: https://github.com/zjhpure/algorithmPractice/blob/master/src/main/java/org/pure/algorithm/invertBinaryTree/Main.java

Original link

Original link: Flip binary tree

Tags: Java Algorithm leetcode

Posted on Wed, 24 Nov 2021 07:04:08 -0500 by stebbi