106.从中序与后序遍历序列构造二叉树 ,105.从中序与先序遍历序列构造二叉树 617.合并二叉树
106.从中序与后序遍历序列构造二叉树
算法过程
- 首先在后序遍历序列中找到根节点(最后一个元素)
- 根据根节点在中序遍历序列中找到根节点的位置
- 根据根节点的位置将中序遍历序列分为左子树和右子树
- 根据根节点的位置确定左子树和右子树在中序数组和后续数组中的左右边界位置
- 递归构造左子树和右子树
- 返回根节点结束
递归位置
- 左子树-中序数组 is = is, ie = ri - 1
- 左子树-后序数组 ps = ps, pe = ps + ri - is - 1 (pe计算过程解释,后续数组的起始位置加上左子树长度-1 就是后后序数组结束位置了,左子树的长度 = 根节点索引-左子树)
- 右子树-中序数组 is = ri + 1, ie = ie
- 右子树-后序数组 ps = ps + ri - is, pe - 1
class Solution {
HashMap<Integer,Integer> memo = new HashMap<>();
int[] post;
public TreeNode buildTree(int[] inorder, int[] postorder) {
for(int i =0; i < inorder.length ; i++)memo.put(inorder[i],i); //存入中序遍历
post = postorder;
TreeNode root = buildTree(0 , inorder.length - 1, 0 ,post.length - 1);
return root;
}
public TreeNode buildTree(int is,int ie, int ps,int pe){
if(ie < is || pe < ps)return null; //如果遍历完一颗子树则结束
int root = post[pe]; //得到根节点
int ri = memo.get(root); //通过根节点位置将中序遍历分为左右子树
TreeNode node = new TreeNode(root); //构造新树
node.left = buildTree(is, ri - 1, ps , ps + ri - is - 1);
node.right = buildTree(ri + 1, ie , ps + ri -is, pe - 1);
return node;
}
}
105.从中序与先序遍历序列构造二叉树
跟上面那题类似,但是找的先序
递归位置
- 左子树-中序数组 is = is , ie = ri - 1
- 左子树-先序数组 ps = ps + 1, pe = ps + ri - is (pe计算过程解释,后续数组的起始位置加上左子树长度 就是后后序数组结束位置了,左子树的长度 = 根节点索引-左子树)
- 右子树-中序数组 is = ri + 1, ie = ie
- 右子树-先序数组 ps = ps + ri + 1 - is, pe
class Solution {
HashMap<Integer,Integer> hm = new HashMap<>();
int[] post;
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i = 0; i < inorder.length; i++)hm.put(inorder[i], i);
post = preorder;
TreeNode root = buildTree (0 , inorder.length - 1,0 , preorder.length - 1);
return root;
}
public TreeNode buildTree(int is, int ie, int ps, int pe){
if(is > ie || ps > pe)return null;
int root = post[ps]; // 从先序获取根节点
int ri = hm.get(root); // 获取中序中根节点位置
TreeNode node = new TreeNode(root);
node.left = buildTree(is ,ri - 1, ps + 1,ps + ri - is );
node.right = buildTree(ri + 1, ie , ps + ri - is + 1, pe);
return node;
}
}
617.合并二叉树
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return MaxTree(nums,0,nums.length );
}
public TreeNode MaxTree(int[] nums,int left , int right){
if(right - left < 1)return null;
if(right - left == 1)return new TreeNode(nums[left]);
int max = nums[left];
int maxIndex = left;
for(int i = left; i < right; i++){
if(max < nums[i]){
max = nums[i];
maxIndex = i;
}
}
TreeNode node = new TreeNode(max);
node.left = MaxTree(nums, left , maxIndex);
node.right = MaxTree(nums, maxIndex + 1 , right);
return node;
}
}
和上面差不多,只不过这次找的最大值,然后再分开左右子树