class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not (preorder and inorder): return None
root = TreeNode(preorder[0])
num = [root]
index = 0
for i in range(1, len(preorder)):
value = preorder[i]
cur = num[-1]
if cur.val != inorder[index]:
cur.left = TreeNode(value)
num.append(cur.left)
else:
while num and num[-1].val == inorder[index]:
cur = num.pop()
index += 1
cur.right = TreeNode(value)
num.append(cur.right)
return root
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
HashMap<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for(int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return build(preorder, 0, preorder.length-1, inorder, 0, inorder.length-1);
}
private TreeNode build(int[] pre, int pS, int pE, int[] in, int iS, int iE) {
if(iS > iE) {
return null;
}
int val = pre[pS];
TreeNode node = new TreeNode(val);
int idx = map.get(val);
int len = idx - iS;// 保存中序左子树个数,用来确定前序数列的个数
node.left = build(pre, pS+1, pS+len, in, iS, idx-1);
node.right = build(pre, pS+len+1, pE, in, idx+1, iE);
return node;
}
}
共以下 39 个回答
利用前序遍历和中序遍历的特点找根节点,根据根节点分治
想清楚build的参数
先找根节点,然后根据根节点分治
时间O(n)空间O(n)
核心思想:
二叉树先序遍历:【根|左子树|右子树】
二叉树中序遍历:【左子树|根|右子树】
找到根在inorder中的位置,划分inorder为左右子树序列,递归,直到inorder长度为0或者1
时间复杂度:O(n)
空间复杂度:O(n)
思路:前序(第一个原素为根节点)和后序(最后一个元素为根节点)用来找根节点,中序遍历用来区分左子树、根节点、右子树.
时间复杂度 O(N)
空间复杂度 O(N)
1、前序遍历的首节点就是根,找到其在中序中的位置i,则中序的前i-1为左子树、前序的1~i也为左子树;右子树同理,对左右采用递归
2、时间O(n),空间O(n)
//递归建立二叉树& pre,vector & in,int l,int r,int start,int end ){& preorder, vector & inorder) {
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode fun(vector
if(l>r) return nullptr;
int target=pre[l];
int pos=-1;
for(int i=start;i<=end;++i){
if(in[i]target){
pos=i;
break;
}
}
TreeNode* newnode=new TreeNode(target);
int len = pos-start;
newnode->left=fun(pre,in,l+1,l+len,start,pos-1);
newnode->right=fun(pre,in,l+len+1,r,pos+1,end);
return newnode;
}
TreeNode* buildTree(vector
int n=preorder.size();
return fun(preorder,inorder,0,n-1,0,n-1);
};
前序和后序这两者同中序之间的关系
也就是中间节点位置
细节:明确位置编号是前闭后开还是前逼后闭
递归就完事了!
时间复杂度on
时间 O(n) 空间 O(n)
解题思路:根节点在前序遍历中的子树节点中的第一个,通过构建哈希表快速找到其在中序遍历中的位置,左右子树分别位于中序遍历根节点的两端,再找到左右子树开始和结束的索引,递归调用子树构造得到最终结果。
时间复杂度:O(n)
空间复杂度:O(n)
时间O(n),空间O(n)
空间时间复杂度O(n)
时间复杂度为O(n),空间复杂度为O(n)
思路:根据前序遍历和中序遍历的特点构建二叉树,用代码实现就行。
实现方式有递归,可以在递归中确定根节点位置的下标,这样时间复杂度应该为O(N^2),空间复杂度为O(height(树的高度))。如果先用map存储中序遍历中值与下标位置之间的关系,那递归中确定根节点位置的下标的时间复杂度就为O(1),递归N次,总的时间复杂度为O(N),空间复杂度为O(N(一个哈希表的空间))。
实现方式还可以是迭代:想想如果这颗二叉树是一个只有左子树的单链表,那么前序和中序它们是不是逆序的,要考虑右子节点什么时候出现。时间复杂度O(N),空间复杂度取决于栈中同时存放的最多节点个数,为O(height)。
递归,本来是想遍历查找的i的位置,看了视频才想到可以用map
时间O(n)
空间O(n)
寻找左子树和右子树节点部分还是觉得有点迷糊,需要再仔细看一下
迭代思想,用前序作为C位,中序作为辅助位,我们去遍历前序结点的同时,去判别和移动中序列表,如果当前结点的值和中序不同,则还没有到最左,把前序的值付给结点的左边,如果相同,返还前一结点,看是否和中序列表相同,不同了,则左到尽头,把前序列表的值付给结点的右边,还是不好想,我想的是用前序的根和中序的根,把中序作为C位判别,但不得行。 时间复杂度O(n) 空间复杂度O(n)
1、根据前序遍历和中序遍历来重建二叉树,要注意前序遍历和中序遍历的性质及其之前的关系
2、前序遍历的第一个元素为根节点,找到这个节点在中序遍历中的位置,在中序遍历中往前是左子树节点,往后是右子树节点,根据左子树节点数量,也能在前序遍历中判断出哪些是左子树节点,哪些是右子树节点
3、那如何找到根节点在中序遍历中的位置呢?利用map容器,重建二叉树之前先将中序遍历的节点值和其位置索引存入map中
时间复杂度O(n) 空间复杂度O(n)
剑指 Offer 07. 重建二叉树(10.31)
递归
106. 从中序与后序遍历序列构造二叉树(10.31)
递归
递归
时间:O(n),空间:O(n)