[Ox-off wins the offer] rebuild binary tree

Topic connection: https: //www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6

Topic effect: a given binary tree preorder and inorder traversal result, the establishment of binary tree. Binary input guarantee no duplicate nodes.

 

Thinking

First look preorder and inorder traversal.

Preorder is to visit the left subtree, then visit the current node, the last visit right subtree.

Preorder is to visit the left subtree, then visit the right subtree, last access to the current node.

As the title promised to create a repeating binary tree node does not exist, we can use the preorder and inorder traversal features to create a binary tree.

 

In the first sequence {1, 2, 4, 7, 3, 5, 6, 8} and {order 4, 7, 2, 1, 5, 3, 8, 6} as an example, the root of the whole tree apparent must be the first point of a preorder traversal, i.e. 1.

1 in order to find the sequence 4,7,2 is left of the left subtree 1, 5,3,8,6 is the right subtree 1 on the right.

Observed again left subtree {2,4,7} / {4,7,2}, similarly to the first node in the sequence is the sequence root of the left subtree, i.e. 2.

2,2 found in the left sequence {4,7} is the sequence of its left subtree is the last one of two sequence series, it is not right subtree.

Look {4,7} / {4,7} subtree tree, the tree only two sub-tree nodes, and the first sequence and the sequence preorder is the same, obviously is the root 4, 7 is a right child leaf nodes of the tree. Conversely, if a {4,7} / {7,4}, then the root node 4, 7 to the left leaf node.

So far it has been left half of the entire tree:

Looking back right subtree 1 {3,5,6,8} / {5,3,8,6}, apparently subtree tree root node is 3, {5} / {5} It is left subtree, {6,8} / {8,6} is a right subtree.

In the left subtree {5} / {5} is only one node.

In the right subtree {6,8} / {8,6}, it is obvious sequence preorder and ordinal variables are not the same, is easy to know the root node 6, 8 is a right leaf node.

Now the whole tree have been:

This analysis is not difficult to find the above process is recursive divide and conquer, according to this line of thought on recursive solution to a problem can write.

 

Code

import java.util.LinkedList;
import java.util.Queue;

/**
 * @author yuan
 * @version 0.1
 * @date 2019/6/4
 */
public class RebuildBinaryTree {

    private class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode(int x) {
            val = x;
        }
    }

    private int[] preorder;
    private int[] inorder;

    /**
     * 递归方法。根据先序和中序遍历序列构建子树。
     *
     * @param preorderStart 子树在先序遍历序列中的第一个结点所在下标
     * @param inorderStart  子树在中序遍历序列中的第一个结点所在下标
     * @param num           子树结点数目
     * @return 子树根结点
     */
    private TreeNode reConstructBinaryTree(int preorderStart, int inorderStart, int num) {
        TreeNode root = null;
        if (inorderStart >= inorder.length || preorderStart < 0) {
            return root;
        }
        if (num == 1) {
            root = new TreeNode(preorder[preorderStart]);
            return root;
        } else if (num == 2) {
            root = new TreeNode(preorder[preorderStart]);
            // 先序和中序一样则应为根+右子结点,否则为根+左子结点
            if (preorder[preorderStart] == inorder[inorderStart]) {
                root.right = new TreeNode(preorder[preorderStart + 1]);
            } else {
                root.left = new TreeNode(preorder[preorderStart + 1]);
            }
            return root;
        }
        TreeNode left = null;
        TreeNode right = null;
        // 根结点必为先序第一个,据此查找根结点在中序中的位置
        for (int i = inorderStart; i < inorderStart + num; i++) {
            if (inorder[i] == preorder[preorderStart]) {
                // i大于inorderStart说明左子树存在,左子树先序从preorderStart+1开始,左子树中序从inorderStart开始,左子树结点数目为i-inorderStart
                if (i > inorderStart) {
                    left = reConstructBinaryTree(preorderStart + 1, inorderStart, i - inorderStart);
                }
                // i小于inorderStart+num-1说明右子树存在,右子树先序从preorderStart+(i-inorderStart)+1开始,右子树中序从i+1开始,右子树结点数目为num-(i-inorderStart)-1
                if (i < inorderStart + num - 1) {
                    right = reConstructBinaryTree(preorderStart + i - inorderStart + 1, i + 1, num - i + inorderStart - 1);
                }
                root = new TreeNode(preorder[preorderStart]);
                root.left = left;
                root.right = right;
                break;
            }
        }
        return root;
    }

    public TreeNode reConstructBinaryTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        this.inorder = inorder;
        return reConstructBinaryTree(0, 0, preorder.length);
    }

    /**
     * 测试用,BFS打印
     *
     * @param root 根结点
     */
    public void printTree(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        StringBuilder result = new StringBuilder();
        result.append(root.val);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node.left == null && node.right == null) {
                continue;
            }
            if (node.left != null) {
                queue.offer(node.left);
                result.append(",").append(node.left.val);
            } else {
                result.append(",#");
            }
            if (node.right != null) {
                queue.offer(node.right);
                result.append(",").append(node.right.val);
            } else {
                result.append(",#");
            }
        }
        System.out.println(result.toString());
    }

    public static void main(String[] args) {
//        int[] preorder = {1, 2, 3, 4, 5, 6, 7};
//        int[] inorder = {3, 2, 4, 1, 6, 5, 7};
//        int[] preorder = {1, 2, 4, 3, 5, 6};
//        int[] inorder = {4, 2, 1, 5, 3, 6};
        int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
        RebuildBinaryTree solution = new RebuildBinaryTree();
        solution.printTree(solution.reConstructBinaryTree(preorder, inorder));
    }
}

 

 附牛客网评论区最高赞代码,写法更加简洁

public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
    TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
    return root;
}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
    if(startPre>endPre||startIn>endIn)
        return null;
    TreeNode root=new TreeNode(pre[startPre]);
    for(int i=startIn;i<=endIn;i++)
        if(in[i]==pre[startPre]){
            root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
            root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
            break;
        }
    return root;
}

 

Guess you like

Origin www.cnblogs.com/null-0/p/10978894.html