题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] Output: [3,9,20,null,null,15,7] 示例 2:
Input: preorder = [-1], inorder = [-1] Output: [-1]
限制:
0 <= 节点个数 <= 5000
|
思路
先按照题目自己构建一个二叉树,不考虑代码实现
前序遍历:preorder = [3,9,20,15,7]
中序遍历:inorder = [9,3,15,20,7]
- 前序遍历一定能够确定3是根节点
- 这样在中序遍历中,3左边的值一定是这个根节点的左子树,3右边的值一定是根的右子树
- 3左边只有一个数9,说明这个数的左子树只有一个是9
- 3的右子树有三个值,(15,20,7),然后在看前序遍历,前序遍历中的(20,15,7)一定是根的右子树,所以20一定是3的右孩子
- 然后在看中序遍历,20是右孩子的根节点,那么15一定是20的左孩子,7一定是20的右孩子
- 最后代入前序遍历验证
- 正确
所以一个前序一定能确定一个根,然后在结合后续一定能确定根的左右孩子,这样在去前序遍历和中序遍历中对比,那么一定能构建一个二叉树
实现
不要看下面代码感觉挺多的,其实很简单就是一个递归的过程,只是传递的参数多,然后一行放不下了而已
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(); int length = inorder.length; for (int i = 0; i < length; i++) { indexMap.put(inorder[i], i); } TreeNode root = buildTree(preorder, 0, length - 1, inorder, 0, length - 1, indexMap); return root; }
private TreeNode buildTree(int[] preorder, int preorderStart, int preorderEnd, int[] inorder, int inorderStart, int inorderEnd, HashMap<Integer, Integer> indexMap) { if (preorderStart > preorderEnd) { return null; } int rootVal = preorder[preorderStart]; TreeNode root = new TreeNode(rootVal); if (preorderStart == preorderEnd) { return root; } else { int rootIndex = indexMap.get(rootVal);
TreeNode leftNode = buildTree(preorder, preorderStart + 1, preorderStart + (rootIndex - inorderStart), inorder, inorderStart, rootIndex - 1, indexMap);
TreeNode rightNode = buildTree(preorder, preorderEnd - (inorderEnd - rootIndex) + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd, indexMap); root.left = leftNode; root.right = rightNode; return root; } } }
|
重点有一个地方:
收获
二叉树的前序、中序、后序遍历
小学数学加减法
求左子树中在前序遍历数组结束的索引和右子树中在前序遍历数组的开始索引
这里为什么有的地方加一,有的地方不加一,而有的地方需要减一
这个是在算法中经常会遇到的问题:
其实还是小学数学:
请听题:
一个有六棵树分别叫,0号,1号 ,2号,3号,4号,5号
5号和2号间有几颗树
2号树向右移动几次能到达5号树的位置
5号树向右移动两次是第几颗树
因为索引是从0开始的,所以引号加1,如果索引不是从零开始的直接间就可以了
总结
- 两个数之间的差值,为小的数向大的数移动的次数
- 如果要求两个数之间的数字数量,需要差值减一
博客首先发布于:
https://lvxiaoyi.top/