二叉树的构造
今天来谈二叉树的构造,主要有以下几个问题:
- 最大二叉树
- 前序和中序构造二叉树
- 后序和中序构造二叉树
- 前序和后序构造二叉树
二叉树构造模板,分治模式:
构造整棵树 = 根节点 + 构造左子树 + 构造右子树
一、最大二叉树
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return build(nums, 0, nums.length-1);
}
//根据数组构造一个树,需要知道数组的本身和用到数组哪一部分
TreeNode build(int[] nums, int left, int right) {
if(left > right) return null;
//寻找最大值以及对应的索引,最大值用来构造根节点,索引用来构造子树
int index = -1; int max = Integer.MIN_VALUE;
for(int i=left; i<=right; i++) {
if(nums[i] > max) {
index = i;
max = nums[i];
}
}
//构造根节点
TreeNode root = new TreeNode(max);
//构造左右子树
root.left = build(nums, left, index-1);
root.right = build(nums, index+1, right);
return root;
}
}
二、前序和中序构造二叉树
class Solution {
Map<Integer,Integer> valToIndex = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i=0; i<inorder.length; i++) {
valToIndex.put(inorder[i],i);
}
return build(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
TreeNode build(int[] preorder, int preleft, int preright, int[] inorder, int inleft, int inright) {
//终止条件
if(preleft > preright || inleft > inright) return null;
//找到中序遍历的根节点及其对应的索引
int rootVal = preorder[preleft];
int index = valToIndex.get(rootVal);
int leftSize = index - inleft;
//构造二叉树
TreeNode root = new TreeNode(rootVal);
root.left = build(preorder,preleft+1,preleft+leftSize,inorder,inleft,index-1);
root.right = build(preorder,preleft+leftSize+1,preright,inorder,index+1,inright);
return root;
}
}
三、后序和中序构造二叉树
class Solution {
Map<Integer,Integer> valToIndex = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i=0; i<inorder.length; i++) {
valToIndex.put(inorder[i],i);
}
return build(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
}
TreeNode build(int[] inorder, int inleft, int inright, int[] postorder, int postleft, int postright) {
//终止条件
if(inleft > inright || postleft > postright) return null;
//找到中序遍历的根节点及其对应的索引
int rootVal = postorder[postright];
int index = valToIndex.get(rootVal);
int leftSize = index - inleft;
//构造二叉树
TreeNode root = new TreeNode(rootVal);
root.left = build(inorder,inleft,index-1,postorder,postleft,postleft+leftSize-1);
root.right = build(inorder,index+1,inright,postorder,postleft+leftSize,postright-1);
return root;
}
}
四、前序和后序构造二叉树
class Solution {
Map<Integer,Integer> valToIndex = new HashMap<>();
public TreeNode constructFromPrePost(int[] preorder, int[] postorder) {
for(int i=0; i<postorder.length-1; i++) {
valToIndex.put(postorder[i],i);
}
return build(preorder,0,preorder.length-1,postorder,0,postorder.length-1);
}
TreeNode build(int[] preorder, int preleft, int preright, int[] postorder, int postleft, int postright) {
if(preleft > preright) return null;
//一定要加这一句
if(preleft == preright) return new TreeNode(preorder[preleft]);
int rootVal = preorder[preleft];
//这里假设左子树根节点存在,其实也可以不存在,所以导致前+后构造的二叉树不唯一
int leftRootVal = preorder[preleft+1];
int index = valToIndex.get(leftRootVal);
int leftSize = index-postleft+1;
TreeNode root = new TreeNode(rootVal);
root.left = build(preorder,preleft+1,preleft+leftSize,postorder,postleft,index);
root.right = build(preorder,preleft+leftSize+1,preright,postorder,index+1,postright-1);
return root;
}
}
总结
- 根据前序和中序或者后序和中序构造二叉树三步走:(1)left>right 终止 (2)寻找根节点及其索引 (3)构造根节点、左右子树
- 根据前序和后序构造二叉树三步走:(1)left>right 终止 (2)left == right 返回新的根节点 (3)寻找根节点、左子树根节点及其索引 (3)构造根节点、左右子树
题目链接
leetcode-654:最大二叉树
leetcode-105:从前序和中序遍历构造二叉树
leetcode-106:从后序和中序构造二叉树
leetcode-889:根据前序和后序遍历构造二叉树
环环无敌大可爱
💃