chapter_divide_and_conquer/build_binary_tree_problem/ #615
Replies: 22 comments 33 replies
-
考研挺喜欢考这种题的 |
Beta Was this translation helpful? Give feedback.
-
难点是如何把过程用编程语言表示出来,用指针把自己想要的操作表达出来,还得注意他们之间的约束关系 |
Beta Was this translation helpful? Give feedback.
-
一个小改进, |
Beta Was this translation helpful? Give feedback.
-
k神, 如果把9去掉, 这个树退化成只有一边, 根节点就不存在左子树, 也就L的初始值不存在, i+1也不是左子树的根, 这个算法是不是就不适用了 |
Beta Was this translation helpful? Give feedback.
-
用这种方式构建的树节点的值不能是一样的吧!因为map的key值必须唯一! |
Beta Was this translation helpful? Give feedback.
-
看理论部分感觉很难,但是代码实现居然如此简洁,这就是分治的魅力吗 |
Beta Was this translation helpful? Give feedback.
-
图12-8也太酷了吧,hhh,厉害 |
Beta Was this translation helpful? Give feedback.
-
root.left = dfs(preorder, inorderMap, i + 1, l, m - 1); |
Beta Was this translation helpful? Give feedback.
-
Hi, 请问有考虑添加:已知 后序和中序遍历 构建树的情形吗?我在构建时遇到下面一个问题,以本章后序遍历树为例:
|
Beta Was this translation helpful? Give feedback.
-
讲解很棒,也希望加些更详细的说明。比如这里中序是用来确定左右子树长度,进而在前序中确定左右子树(的根节点)下标。后序加中序重建也类似的道理。不过简洁点也好,要是当年在学数据结构时能看到hello算法就好了。。。 |
Beta Was this translation helpful? Give feedback.
-
/* 构建二叉树:分治 */
TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
// 子树区间为空时终止
if (r - l < 0)
return NULL;
// 初始化根节点
TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode));
root->val = preorder[i];
root->left = NULL;
root->right = NULL;
// 查询 m ,从而划分左右子树
int m = inorderMap[preorder[i]];
// 子问题:构建左子树
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1, size);
// 子问题:构建右子树
root->right = dfs(preorder, inorderMap, i + 1 + m - l, m + 1, r, size);
// 返回根节点
return root;
} 思考不下去,没想明白它这个“递”的过程会怎样结束,就是可以知道如果左子树(右子树)为空的话就就不在进行构建左子树(右子树),比如当m-l=0时说明没有左子树了,就是在建立节点9的那个函数(也就是第二函数),里面还会有root->left=dfs(preoder,inorderMap,i+1,l,m-1,size)//此时i为2,l为0,m-1为0,很混乱。我的想法是需要在root->left=dfs(......)前面加if(m!=l)//如果相等代表左子树没了就不再进行。应该是还没没理解,所以来请教一下 |
Beta Was this translation helpful? Give feedback.
-
12.3的代码有点难,如果有需要的小伙伴可以邮箱私我,我自己画了个步骤图,可以方便理解 |
Beta Was this translation helpful? Give feedback.
-
当前树是什么意思,没太看懂 |
Beta Was this translation helpful? Give feedback.
-
public class BuildTree {
/**
*
* @param preorder 二叉树的前序遍历结果
* @param inorderMap 二叉树的中序遍历结果
* @param rootInPre 要构建的子树根节点在前序遍历中的索引
* @param left 要构建的子树的左子节点在中序遍历中的索引
* @param right 要构建的子树的右子节点在中序遍历中的索引
* @return 构建出的树根节点
*/
public TreeNode dfs(int[] preorder, Map<Integer,Integer> inorderMap, int rootInPre, int left, int right){
if (left>right){
//左子节点的索引大于右子节点的索引,即无子节点
return null;
}
TreeNode treeNode=new TreeNode();
treeNode.val =preorder[rootInPre];
//根节点在中序遍历中的索引
int rootInIn=inorderMap.get(preorder[rootInPre]);
treeNode.left=dfs(preorder,inorderMap,rootInPre+1,left,rootInIn-1);
treeNode.right=dfs(preorder,inorderMap,rootInPre+1+rootInIn-left,rootInIn+1,right);
System.out.println(treeNode);
return treeNode;
}
public TreeNode buildTree(int[] preorder,int[] inorder){
Map<Integer,Integer>inorderMap=new HashMap<>();
for (int i = 0; i < inorder.length; i++) {
inorderMap.put(inorder[i],i);
}
return dfs(preorder,inorderMap,0,0,inorder.length-1);
}
public static void main(String[] args) {
new BuildTree().buildTree(new int[]{3,9,2,1,7},new int[]{9,3,1,2,7});
}
}
public TreeNode() {
}
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int value, TreeNode left, TreeNode right) {
this.val = value;
this.left = left;
this.right = right;
} |
Beta Was this translation helpful? Give feedback.
-
public static void main(String[] args) {
System.out.println(new BuildTree().buildTreeByPost(new int[]{8, 6, 9, 1, 7, 2, 3}, new int[]{8, 9, 6, 3, 1, 2, 7}));
}
public TreeNode buildTreeByPost(int[] postorder,int[] inorder){
Map<Integer,Integer> inorderMap=new HashMap<>();
System.out.println(Arrays.toString(inorder));
for (int i = 0; i < inorder.length; i++) {
inorderMap.put(inorder[i],i);
}
System.out.println(inorderMap);
return dfsPost(postorder,inorderMap,postorder.length-1,0,inorder.length-1);
}
/**
*
* @param postorder 后序遍历的结果
* @param inorderMap 中序遍历的结果Map集合
* @param rootInPost 要构建的树的根节点在后续遍历中的索引
* @param left 要构建的树的最左子节点在中序遍历中的索引
* @param right 要构建的树的最右子节点在中序遍历中的索引
* @return 要构建的树的根节点
*/
public TreeNode dfsPost(int[] postorder,Map<Integer,Integer> inorderMap,int rootInPost,int left,int right){
if (left>right) return null;
TreeNode treeNode=new TreeNode();
treeNode.val=postorder[rootInPost];
//根节点在中序遍历中的索引
int rootInIn=inorderMap.get(postorder[rootInPost]);
//右子树节点的数量
int rightTreeNodeNum=right-rootInIn;
treeNode.left=dfsPost(postorder,inorderMap,rootInPost-rightTreeNodeNum-1,left,rootInIn-1);
treeNode.right=dfsPost(postorder,inorderMap,rootInPost-1,rootInIn+1,right);
return treeNode;
} |
Beta Was this translation helpful? Give feedback.
-
如果二叉树中有值重复的节点的情况该如何实现呢 |
Beta Was this translation helpful? Give feedback.
-
class TreeNode {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
}
function buildTree(preorder, inorder) {
if (preorder.length === 0) {
return null;
}
let root = new TreeNode(preorder[0]);
let index = inorder.indexOf(preorder[0]);
root.left = buildTree(preorder.slice(1, index + 1), inorder.slice(0, index));
root.right = buildTree(preorder.slice(index + 1), inorder.slice(index + 1));
return root;
} |
Beta Was this translation helpful? Give feedback.
-
这章脑子有点不够用了~这么建树的意义是什么?有没有大佬用简单易懂的话给指点一下? |
Beta Was this translation helpful? Give feedback.
-
试了下举一反三,由前序加后序来还原二叉树,发现无法实现,因为在链表情况下,不借助中序遍历序列无法确定树的左右偏情况,必须由中序加上前序后续二者其一才能反推二叉树 |
Beta Was this translation helpful? Give feedback.
-
前中后序遍历 豁然开朗了 |
Beta Was this translation helpful? Give feedback.
-
不是很理解,为什么左子树是 “i+1",如果左子树不只是一个节点,还能用”i+1“吗? |
Beta Was this translation helpful? Give feedback.
-
好精妙,每一个子树的前序遍历的首元素就是子树的根节点, 然后找出这个根节点在中序遍历的位置,以该根节点为基准继续划分下一个左右子树 |
Beta Was this translation helpful? Give feedback.
-
chapter_divide_and_conquer/build_binary_tree_problem/
动画图解、一键运行的数据结构与算法教程
https://www.hello-algo.com/chapter_divide_and_conquer/build_binary_tree_problem/
Beta Was this translation helpful? Give feedback.
All reactions