https://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13&tqId=11157&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
考研的时候闭着眼写的题目吭哧了半天……
首先一个技巧是把中序的数组存成了Map的形式,每次在根据value找到相应下标的时候O(1),空间换时间的方法。
其次牛客网上的函数的入参是两个数组,这样在递归的时候每次要传不同的数组,就涉及到同一组数据的来回复制,浪费空间,所以重新定义了一个方法,在新定义的方法上递归而不是在题目提供的方法上递归。新的方法的入参包括pre in数组,这两个数组是不变的,在递归的不同时候使用数组里的不同的部分,即start end这四个索引值。
当然递归最重要的是递归终止的条件,以及递归终止后该返回什么值。在本体中,递归终止意味着用来重建一个节点的左子树or右子树的节点的个数为0,那么此时其相应的左子树or右子树应该返回为null。那么当子树的节点个数为0的时候就是下表索引非法的时候。
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ import java.util.Arrays; import java.util.HashMap; public class Solution { public TreeNode reConstructBinaryTree(int [] pre,int [] in) { if(pre==null || in==null){ return null; } HashMap<Integer, Integer> map = new HashMap<>(); for(int i=0; i<in.length; i++){ map.put(in[i], i); } return reBuild(pre,0,pre.length-1,in,0,in.length-1,map); } public TreeNode reBuild(int[] pre, int preStart, int preEnd, int[] in, int inStart, int inEnd, HashMap<Integer,Integer> map){ if(preStart>preEnd || inStart>inEnd){ return null; } //找出根节点在中序里的索引 int rootIndex = map.get(pre[preStart]); TreeNode root = new TreeNode(pre[preStart]); root.left = reBuild(pre,preStart+1,preStart+rootIndex-inStart, in,inStart,rootIndex-1, map); root.right = reBuild(pre, preStart+rootIndex-inStart+1,preEnd, in, rootIndex+1,inEnd, map); return root; } }