剑指offer 07 & LeetCode 105 重建二叉树
题目
题目链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof/
初步题解
先放代码:
/**
* 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
// TreeNode* re = nullptr;
if(preorder.empty()){
return nullptr;
}
//根节点
TreeNode* root = new TreeNode(preorder[0]);
// root->val = inorder[0];
vector<int> lPreorder,rPreorder;
vector<int> lInorder,rInorder;
int midIndex = 0;
for(int i = 0; i<inorder.size() ; i++){
if(inorder[i]==preorder[0]){
midIndex = i;
break;
}
}
// 获取左右子树的结点数量
int leftSize = midIndex;
int rightSize = preorder.size() - midIndex - 1;
// 分开赋值
for(int i=0 ; i<midIndex ; i++){
lInorder.push_back(inorder[i]);
// lPreorder[i]=preorder[i];
}
for(int i=midIndex+1 ; i<inorder.size() ; i++){
rInorder.push_back(inorder[i]);
// lPreorder[i-midIndex-1]=preorder[i];
}
for(int i=1 ; i<leftSize+1 ; i++){
lPreorder.push_back(preorder[i]);
// lInorder[i-1] = inorder[i];
}
for(int i=leftSize+1 ; i<preorder.size() ; i++){
rPreorder.push_back(preorder[i]);
// rInorder[i-1] = inorder[i];
}
//左子树
root->left = buildTree(lPreorder,lInorder);
//右子树
root->right = buildTree(rPreorder,rInorder);
return root;
}
};
思路很简单,先序遍历时,根节点的值会被放在第一个。而中序遍历时,根节点的值刚好把左右子树全部的值分隔开,就是利用这一句话的思路做题。我们只要先按照先序遍历分隔开中序遍历为左子树和右子树的值,然后在分别对左右子树进行递归操作就可以了。
递归退出点的选择:返回的值是树的结点指针,也就是作为父节点的左右子结点来用。这样只要最后不满足条件时返回null就可以了。至于退出条件,就是传入的先序遍历(或后序遍历)所承载的数组为空就可以退出了。
但是这样做结果很慢:
而实际上比较快的只需要24ms,足足慢了10倍,必须要优化。
优化
存在两个优化点。第一个是每次都要搜索root节点在中序遍历中的位置,第二个是每次都要来回创建新的vector来存放中序遍历的左右子树再往下递归,这个创建vector并赋值的过程其实很耗时间。
针对一个点,可以创建一个全局的map来避免每次都查找,不然每一次递归都要寻找根节点的位置。
针对第二个点,选择传index,而不是重新赋值来做,这样节省了大量的时间。
优化后的代码
/**
* 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:
map<int,int> inorder_map;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i=0;i<inorder.size();i++){
// 方便一下找到大小为i的元素在哪个位置了,省去了遍历浪费的时间
inorder_map[inorder[i]]=i;
}
TreeNode* root = new TreeNode;
root = Recur_buildTree(preorder, inorder, 0, preorder.size()-1, 0, inorder.size()-1);
return root;
}
TreeNode* Recur_buildTree(vector<int>& preorder, vector<int>& inorder, int pre_start, int pre_end, int in_start, int in_end){
if(pre_start > pre_end || in_start > in_end){
return nullptr;
}
//根节点
TreeNode* root = new TreeNode(preorder[pre_start]);
int mid_index = inorder_map[preorder[pre_start]];
// 获取左子树的结点数量
int left_size = mid_index - in_start;
//左子树
root->left = Recur_buildTree(preorder, inorder, pre_start + 1, pre_start + left_size, in_start, in_start + left_size -1);
//右子树
root->right = Recur_buildTree(preorder, inorder, pre_start + left_size + 1, pre_end, mid_index+1, in_end);
return root;
}
};
优化后的速度:
剑指offer 07 & LeetCode 105 重建二叉树的更多相关文章
- 剑指Offer - 九度1385 - 重建二叉树
剑指Offer - 九度1385 - 重建二叉树2013-11-23 23:53 题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的 ...
- 剑指offer面试题6 重建二叉树(c)
- 剑指offer面试题6 重建二叉树(java)
注:(1)java中树的构建 (2)构建子树时可以直接利用Arrays.copyOfRange(preorder, from, to),这个方法是左开右闭的 package com.xsf.SordF ...
- 剑指offer第二版-7.重建二叉树
描述:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.假设前序遍历或中序遍历的结果中无重复的数字. 思路:前序遍历的第一个元素为根节点的值,据此将中序遍历数组拆分为左子树+root+右子树,前序遍 ...
- 《剑指Offer》面试题-重建二叉树
题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7 ...
- 剑指offer【04】- 重建二叉树(java)
题目:重建二叉树 考点:树 题目描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6, ...
- 剑指offer(4)重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- 【剑指offer】 Java实现重建二叉树
GitHub上的代码链接 /** * @Author: DaleyZou * @Description: 重建二叉树 * 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. * 假设输入的前序 ...
- 【剑指Offer】4、重建二叉树
题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列 ...
随机推荐
- 恢复HTML表格笔记
表格 语法: 标记: <table></table>:表示一个表格 属性: ...
- Springboot快速入门篇,图文并茂
Springboot快速入门篇,图文并茂 文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! image-20 ...
- 手把手教你NLTK WordNet使用方法
最近看了WordNet,0基础入门,简单记下笔记.因为本身不是学自然语言处理的,好多名词不是特别清楚,现有的博客读的晕乎乎,所以重新写了这个,理清思路.除了行文中提到的链接,其他几个有用的参考链接如下 ...
- 聊聊mysql中的int(1)
昨天有个读者问了我这样一个问题在mysql中建表的时候,我设置一个字段为int类型,长度为1,但是我发现这个字段却可以存储任意长度的数字,这是什么情况?这个问题在我刚接触数据库的时候也遇到过,我觉得有 ...
- kafka-clients 1.0 高阶API消费消息(未完)
消费消息的请求(按序) org/apache/kafka/common/requests/RequestHeader org/apache/kafka/common/requests/ApiVersi ...
- PHP基础之常量与变量
1.变量:用来存储信息的空间大小 $var 2.常量:定义之后不可以更改,标识符,并且给其赋值,常量是全局,在整个页面中均可使用,常量一般有英文字母.下划线.数字组成,开头不能是数字和$ 使用defi ...
- guzzlehttp中的坑之带子目录的域名
1.问题: 线上开发环境配的是带子目录的域名,例如:https://aa.com/bb.使用nginx的location代理到项目的根目录.在代码中使用guzzlehttp访问这域名下的API时,一直 ...
- mysql索引类型:FULLTEXT、NORMAL、SPATIAL、UNIQUE的区别
1. Normal 普通索引 2. Unique 唯一索引 3. Full Text 全文索引 4. SPATIAL 空间索引 5. btree索引和hash索引的区别 6. 在实际操作过程中,应该选 ...
- 第6篇 Scrum 冲刺博客
1.站立会议 照骗 进度 成员 昨日完成任务 今日计划任务 遇到的困难 钟智锋 重构游戏逻辑代码 改写部分客户端代码,制作单机版 庄诗楷 进行了相关的装饰改进 与其他部分合成完成游戏 合成遇到bug, ...
- 牛客网PAT练兵场-查验身份证
题解:模拟题,直接算 题目地址:https://www.nowcoder.com/questionTerminal/779a72a420744b1d9c0ec7b7a8dd8f39 /** * *作者 ...