Bootstrap

剑指offer004-重建二叉树

1.题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

 

例如,给出

前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:

    3
   / \
  9  20
    /  \
   15   7
 

限制:

0 <= 节点个数 <= 5000
2.分析
  • 首先想到递归实现
  • public void rebuild(TreeNode node, int start, int end, int[] preorder, int[] inorder);
  • node是这次要构建的节点,start和end代表要构建的inorder的起始位置和结束位置
  • 我采用中序构建,所以构建的顺序就是preorder中数的顺序,所以采用一个全局变量prePosition来记录该取第几个数。
  • 在inorder[start, end]中找到preorder[prePosition]
  • 然后分左子树,右子树,递归。
3.我的代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    static int prePosition = 0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        TreeNode root = new TreeNode();
        // 空数组直接返回null
        if (preorder.length == 0)
            return null;
        rebuild(root, 0, preorder.length - 1, preorder, inorder);
        prePosition = 0; //这个地方一定要注意,因为是static,而后台会多次调用此方法,注意每次计算要清0;
        return root;
    }

    public void rebuild(TreeNode node, int start, int end, int[] preorder, int[] inorder) {
        if (start == end) {
            node.val = preorder[prePosition];
            prePosition++;
            return;
        } else if (start > end){ // 对应只有一个数的数组情况
            return;
        }
        node.val = preorder[prePosition];
        int number = preorder[prePosition];
        prePosition++;
        int position = -1;
        for (int i = start; i <= end; i++) {
            if (inorder[i] == number) {
                position = i;
                break;
            }
        }
        if (start <= position - 1) {
            TreeNode leftNode = new TreeNode();
            node.left = leftNode;
        }
        if (position + 1 <= end) {
            TreeNode rightNode = new TreeNode();
            node.right = rightNode;
        }
        rebuild(node.left, start, position - 1, preorder, inorder);
        rebuild(node.right, position + 1, end, preorder, inorder);
    }
}
4.题解代码

采用HashMap来存位置,太妙了!!

class Solution {
    int[] preorder;
    HashMap<Integer, Integer> dic = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
        for(int i = 0; i < inorder.length; i++)
            dic.put(inorder[i], i);
        return recur(0, 0, inorder.length - 1);
    }
    TreeNode recur(int root, int left, int right) {
        if(left > right) return null;                          // 递归终止
        TreeNode node = new TreeNode(preorder[root]);          // 建立根节点
        int i = dic.get(preorder[root]);                       // 划分根节点、左子树、右子树
        node.left = recur(root + 1, left, i - 1);              // 开启左子树递归
        node.right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                           // 回溯返回根节点
    }
}
;