https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
解题思路:
这题是二叉树遍历中比较难的题目,但是也比较常见,考的是对pre、in或者post遍历的更深的理解。
http://articles.leetcode.com/2011/04/construct-binary-tree-from-inorder-and-preorder-postorder-traversal.html
主要是参考上面这个文章的思路。
对于下面的二叉树:
7
/ \
10 2
/ \ /
4 3 8
\ /
1 11
preorder的遍历结果:7 10 4 3 1 2 8 11
inorder的便利结果: 4 10 3 1 7 11 8 2
要解决这道题目,就要分别利用preorder和inorder遍历的两个性质。preoder的第一个元素确定为根节点,然后再在inorder里,它左侧的就是左子树的全部节点,右侧的就是右子树的全部节点。然后再对左子树这些节点,递归调用上面的方法。
比如,上面的例子,7为preorder的第一个元素,所以是整个树的根。那么在inorder中,7往左的4-1是左子树,往右的11-2是右子树。我们回到preorder中,10为左子树的根,2为右子树的根。再去preorder里面,10左侧的4为左子树,右侧的3、1为右子树。2往左的11和8为左子树。再递归,直至结束。
所以这里递归的,其实是preorder和inorder这两个数组的左右边界。取root,永远是preorder边界内的第一个元素。然后用root在inorder里的index,去更新下一递归inorder的范围。
preorder的范围如何确定?从root往后算长度,左子树长度的就是左子树范围,右子树长度的,就是右子树范围。
代码如下:
/** * Definition for binary tree * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { return helper(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1); } public TreeNode helper(int[] preorder, int[] inorder, int preStart, int preEnd, int inStart, int inEnd) { if(preStart > preEnd || inStart > inEnd) { return null; } TreeNode node = new TreeNode(preorder[preStart]); int index = 0; for(int i = inStart; i <= inEnd; i++){ if(inorder[i] == preorder[preStart]) { index = i; break; } } node.left = helper(preorder, inorder, preStart + 1, preStart + index - inStart, inStart, index - 1); node.right = helper(preorder, inorder, preStart + index - inStart + 1, preEnd, index + 1, inEnd); return node; } }