[剑指Offer笔记] 06_树 reConstructBinaryTree
树
- 除了根节点之外每个节点只有一个父节点
- 根节点没有父节点
- 除了叶节点之外所有节点都有一个或多个子节点
- 叶节点没有子节点
- 父节点与子节点用指针链接
二叉树
-
每个节点最多有两个子节点
-
最重要的操作:
遍历
-
遍历方式:
-
前序遍历
-
中序遍历
-
后序遍历
上述三种方法,都有递归和循环(非递归)的实现方法,必须掌握!!!
-
广度优先遍历
按层次遍历
-
-
二叉树有很多特例!!!
-
二叉搜索树
-
堆(最大退/最小堆)
有很多快速查找最大值或最小值的问题可以用堆来解决.
-
红黑树
C++STL中,set/multiset/map/multimap等数据结构都是基于红黑树实现的.
-
题目描述:
- 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。
- 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
- 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:
- 用递归的方法.
- 前序遍历的第一个节点肯定是根节点!!!
- 那么,需要在中序遍历中将这个节点找到,就可以将这个树划分成为左右两个子树.然后递归构造!!!
- 注意!!! 索引和长度的计算!!!
实现:
namespace pro6 {
class Solution {
private:
// pre[pre_b,pre_e]表示一棵树
// vin[vin_b,vin_e]表示一颗树
TreeNode *helper(const vector<int> &pre, int pre_b, int pre_e, const
vector<int> &vin, int vin_b, int vin_e) {
// 每次都取 pre[pre_b]作为根节点
int rootVal = pre[pre_b];
TreeNode* root = new TreeNode(rootVal);
/* 递归调用生成其左子树和右子树 */
// 1. 在中序遍历中找到 rootVal的位置 rootIndexInVin;
int rootIndexInVin = 0;
for (int i = vin_b; i <= vin_e; i++) {
if (vin[i] == rootVal) {
rootIndexInVin = i;
break;
}
}
// 2.递归构造左子树和右子树
// 求得左右子树的长度
int LenOfLeftTree = rootIndexInVin - vin_b;
int LenOfRightTree = vin_e - rootIndexInVin;
if(LenOfLeftTree>0)
root->left = helper(pre, pre_b + 1, pre_b + LenOfLeftTree - 1, vin, rootIndexInVin-LenOfLeftTree,rootIndexInVin-1);
if (LenOfRightTree > 0)
root->right = helper(pre, pre_b + LenOfLeftTree + 1, pre_b + LenOfLeftTree + LenOfRightTree, vin, rootIndexInVin + 1, rootIndexInVin + LenOfRightTree);
return root;
}
public:
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
if (pre.size() <=0||vin.size()<0||pre.size()!=vin.size()) {
return NULL;
}
int len = pre.size();
return helper(pre, 0, len - 1, vin, 0, len - 1);
}
};
}
做题体会:
- 将平时推导重建二叉树的过程逻辑化!!!
- 注意:索引和长度的计算!!!