106.从中序与后序遍历序列构造二叉树
思路
按照正常思路走,找到中序序列中在后序序列最靠近尾部的值作为根节点,在中序序列中以该值为中心分出两个序列,分别为左子树与右子树的节点,不断按照上述方法递归,若传入序列大小为1则返回。
总结
按照上述思路,写出来代码,很是辣鸡。题解的递归方法十分巧妙,确定好后序序列的值后(后序序列最后一个值,每次递归往前推一位,所以后序序列不断缩小,因为是后序遍历,从后往前是“中右左”,所以它的值最前面的为左树的值,因此优先遍历右子树,不断向左子树遍历,),传入的是子树的头尾两个指针(中序序列首尾指针),根据指针来保存一个子树的所有节点值。
迭代看不懂
代码
正常思路(辣鸡)
class Solution {
HashMap<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
for (int i=0;i< postorder.length;i++){
map.put(postorder[i],i);
}
TreeNode root=new TreeNode();
root.val=postorder[postorder.length-1];
int size= inorder.length;
build(root,inorder,postorder,size);
return root;
}
public void build(TreeNode root,int[] inorder,int[] postorder,int size){
//若inorder只包含一个节点,则为叶子节点,退出
if (size<2) return;
int[] left=new int[inorder.length];
int[] right=new int[inorder.length];
boolean f=false;
int l_size=0,r_size=0;
for (int j=0;j< size;j++){
if (inorder[j]==root.val) {
f=true;
continue;
}
if (f) {
right[r_size++]=inorder[j];
} else {
left[l_size++]=inorder[j];
}
}
//找到后续数组中最右的值下标作为子树
int l_max=-1,r_max=-1;
for (int j=0;j<l_size;j++){
if (l_max<map.get(left[j])) l_max=map.get(left[j]);
}
for (int j=0;j<r_size;j++){
if (r_max<map.get(right[j])) r_max=map.get(right[j]);
}
TreeNode leftNode=new TreeNode();
TreeNode rightNode=new TreeNode();
if (l_max!=-1) {
leftNode.val=postorder[l_max];
}else leftNode=null;
if (r_max!=-1) {
rightNode.val=postorder[r_max];
}else rightNode=null;
root.left=leftNode;
root.right=rightNode;
build(leftNode,left,postorder,l_size);
build(rightNode,right,postorder,r_size);
}
}
双指针思路
class Solution {
int post_idx;
int[] postorder;
int[] inorder;
Map<Integer, Integer> idx_map = new HashMap<Integer, Integer>();
public TreeNode helper(int in_left, int in_right) {
// 如果这里没有节点构造二叉树了,就结束
if (in_left > in_right) {
return null;
}
// 选择 post_idx 位置的元素作为当前子树根节点
int root_val = postorder[post_idx];
TreeNode root = new TreeNode(root_val);
// 根据 root 所在位置分成左右两棵子树
int index = idx_map.get(root_val);
// 下标减一
post_idx--;
// 构造右子树
root.right = helper(index + 1, in_right);
// 构造左子树
root.left = helper(in_left, index - 1);
return root;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
this.postorder = postorder;
this.inorder = inorder;
// 从后序遍历的最后一个元素开始
post_idx = postorder.length - 1;
// 建立(元素,下标)键值对的哈希表
int idx = 0;
for (Integer val : inorder) {
idx_map.put(val, idx++);
}
return helper(0, inorder.length - 1);
}
}