题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
先贴上完整代码:
1 /** 2 * Definition for binary tree 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 public class Solution { 11 12 public TreeNode reConstructBinaryTree(int [] pre,int [] in) { 13 14 return reconstructBinaryTree(pre, 0, pre. length, in, 0, in.length); 15 } 16 17 18 private TreeNode reconstructBinaryTree(int [] pre, int preStart, int preEnd, int [] in, int inStart, int inEnd) { 19 20 if(inStart == inEnd) 21 return null; 22 23 TreeNode curRoot = new TreeNode(pre[preStart]); 24 25 for(int i = inStart; i < inEnd; i++) { 26 if (in[i] == pre[preStart]) { 27 curRoot.left = reconstructBinaryTree(pre, preStart+1, preStart+i-inStart+1, in, inStart, i); 28 curRoot.right = reconstructBinaryTree(pre, preStart+i-inStart+1, preEnd, in, i+1, inEnd); 29 break; 30 } 31 } 32 33 return curRoot; 34 } 35 }
思路:这题不难想到要用递归,难点是写递归时的一些细节,主要有2点:
1,对当前节点的左右子树递归时实参如何写?
2,递归结束条件如何写?
对于问题1:
只要把握前序是根左右,中序是左根右即可写出,我们知道对左子树递归时传入的是左子树的前序数组和中序数组,那么四个位置实参就应该是
(preStart+1, preStart+i-inStart+1, inStart, i), preStart+1不难理解,前序是根左右嘛,那么preStart+1肯定是当前树的左子树的前序数组的起始位置, 接着左子树前序数组的结尾index怎么写呢?我们只要知道了左子树中节点个数,那么当前preStart+节点个数+1就是结束index了(我的写法是数组包含起始指针,不包含结束指针),又因为中序遍历是左根右,所以节点个数等于 i - inStart,其中i是当前根节点在当前中序数组中的index,所以左子树的结尾index即 preStart+i-inStart+1,同理可以写出其它位置参数,
对于问题2:
可以想出子树中没有节点时就可以直接return null了,而子树中节点的个数就等于递归时传入的 前序数组的结束index - 前序数组的起始index = 中序数组的结束index - 中序数组的起始index , 因为2个一样,所以只要拿一个来判断就行了,如if (inEnd - inStart <= 0) return null; 但是其实写 if (inEnd - inStart == 0) 就行,因为从刚才写出的位置参数可以推出第一次不满足条件时子树的节点个数一定为0.