当前位置: 首页剑指offer刷题第四期问题详情 【二叉树专题】剑指 Offer 07. 重建二叉树 本问题对应课程链接:剑指offer刷题第四期 要求: 1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。 2、给出你代码所用的时间复杂度和空间复杂度
共以下 28 个回答
/**
* 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 {
private:
unordered_map<int, int> index; // 结点和中序遍历位置的对应关系
public:& preorder, vector & inorder, int prel, int prer, int inl, int inr){
TreeNode* tempbuildTree(vector
if(prel > prer) return nullptr;
};
递归区间/分治算法
时间复杂度:有N个节点,初始化HashMap遍历一次inorder,用时O(n)。递归共建立N个节点,每层递归节点建立占用O(1),总共需要O(n)
空间复杂度:HashMap额外使用O(n)的空间 因此是O(n)
ts
时间复杂度:O(n)
空间复杂度:O(n)
时间复杂度:O(n)
空间复杂度:O(n)
“`java
Map< Integer, Integer > map = new HashMap();
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || preorder.length <= 0){ return null; } // 简历中序遍历数组的映射(就是为了快速求出某个元素的下标) for(int i = 0; i < inorder.length; i++) { map.put(inorder[i], i); }
c++代码 递归回调& preorder, vector & inorder) & preorder,int preStart,int preEnd,vector & inorder,int instart,int inEnd)
class Solution {
public:
TreeNode* buildTree(vector
{
return build(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1);
}
TreeNode* build(vector
{
if(preStart>preEnd||instart>inEnd) return NULL;
int val=preorder[preStart];
int index;
TreeNode* temp=new TreeNode(val);
for(int i=0;i<inorder.size();i++)
{
if(valinorder[i])
{
index=i;
break;
}
}
int tleft=index-instart;
temp->left=build(preorder,preStart+1,preStart+tleft+1,inorder,instart,index-1);
temp->right=build(preorder,preStart+tleft+1,preEnd,inorder,index+1,inEnd);
return temp;
}
};
时间复杂度O(n), 空间复杂度O(n)
TS写的
大致懂了,
思路
首先需要了解前序遍历和中序遍历。可知的是前序遍历的第一个为根节点,可以以此作为index来查找在中序遍历中的位置,从而划分出左子树和右子树。
” alt=”在这里插入图片描述” />
以此树为例:
前序遍历为[3, 9, 20, 15, 7]
中序遍历为[9, 3, 15, 20, 7]
其中根节点为[3, 9, 20, 15, 7]中的3,在中序遍历中的位置为[9, 3, 15, 20, 7]。
所以可以划分左右子树为
前序遍历为[3, (9), {20, 15, 7}]
中序遍历为[(9), 3, {15, 20, 7}]
然后可以继续分解为子问题,针对每一个树再重复一次,所以这里需要一个函数。
这个函数需要定义要分解的子树再前序遍历中的左边界l1和右边界r1,以及在中序遍历中的左边界l2和右边界r2。
这是一个递归函数,所以要确定结束条件为左边界超过右边界
然后需要探讨子树的边界怎么划分。
首先要得到根节点在中序遍历中的下标i
对于根节点的左子树,其中序遍历数组为
[(9), 3, {15, 20, 7}]
根节点的下标为
i左子树的左边界为
l2,右边界为i - 1右子树的左边界为
i + 1,右边界为r2前序遍历数组为
[3, (9), {20, 15, 7}]
根节点的下标为
l1左子树的左边界
l1 + 1,右边界为l1 + (i - l2)右子树的左边界为
l1 + (i - l2) + 1,其实就是左子树右边界+1,右边界为r2然后在主函数中先对中序遍历进行映射,然后运行递归函数,得到结果。
代码
九
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int[] preorder;
Map<Integer, Integer> dic = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder = preorder;
for (int i = 0; i < inorder.length; i++)
dic.put(inorder[i], i);
return recur(0, 0, inorder.length – 1);
}
TreeNode recur(int root, int left, int right) {
if (left > right) return null;
TreeNode node = new TreeNode(preorder[root]);
int i = dic.get(preorder[root]);
node.left = recur(root + 1, left, i – 1);
node.right = recur(root + i – left + 1, i + 1, right);
return node;
}
}
“`c++& preorder, vector & inorder) { iLeft(inorder.begin(),k),iRight(k+1,inorder.end()); pLeft(preorder.begin()+1,preorder.begin()+1+n),pRight(preorder.begin()+1+n,preorder.end());
//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:
TreeNode* buildTree(vector
if(preorder.empty()||inorder.empty()) return NULL;
int size=preorder.size();
TreeNode* T= new TreeNode(preorder[0]);
auto k=find(inorder.begin(),inorder.end(),*preorder.begin());
vector
int n=iLeft.size();
vector
T->left=buildTree(pLeft,iLeft);
T->right=buildTree(pRight,iRight);
return T;
}
};
“`
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
//通过 前序遍历划分中序遍历的左右子树
//递归 完成每个子树的构建
if(preorder.length0||preordernull)
{
return null;
}
return buildTree1(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
}
public TreeNode buildTree1(int []preorder,int preorderleft,int preorderright,int [] inorder,int inorderleft,int inorderright)
{
if(preorderleft>preorderright||inorderleft>inorderright)
{
return null;
}
if(inorderleftinorderright)
{
return new TreeNode(inorder[inorderleft]);
}
int find = 0;
for(int i=inorderleft;i<=inorderright;i++)
{
if(preorder[preorderleft]inorder[i])
{
find = i;
}
}
TreeNode root =new TreeNode(preorder[preorderleft]);
root.left=buildTree1(preorder,preorderleft+1,preorderright,inorder,inorderleft,find-1);
root.right=buildTree1(preorder,preorderleft+1+(find-inorderleft),preorderright,inorder,find+1,inorderright); //有坑 对于右子树在前序里的第一个要排除前序里的左子树数量
return root;
}
”’java
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return localTree(preorder,inorder,0,preorder.length,0,inorder.length);
}
//算上起始点,包含起始点
public TreeNode localTree(int[] preorder,int[] inorder,int beginPre,int endPre,int beginOr,int endOr){
if(preorder.length 0 || inorder.length 0){
return null;
}
//前序遍历的该结点一定为root
int val = preorder[beginPre];
TreeNode root = new TreeNode(val);
//找到begin在inorder的位置,将其分为左子树和右子树
int count = beginOr;
for(int i = beginOr;i < endOr;i++){
if(inorder[i] val){
count = i;
break;
}
}
int len = count – beginOr;
int left = beginPre + len;
if(left > beginPre){
root.left = localTree(preorder,inorder,beginPre+1,left+1,beginOr,count);
}
}
时间复杂度O(n)
空间复杂度O(n)
”’
时间复杂度O(n),空间复杂度O(n)
Day9:下面是代码
时间复杂度:O(N)
空间复杂度:O(N)
前序遍历的第一个元素为根节点,在中序遍历中根节点左边为左子树右边为右子树
Definition for a binary tree node.
class TreeNode:
def init(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if not preorder:
return None
时间复杂度:O(n)
空间复杂度:O(n)