一、回顾前、中、后序遍历
1.1、前序遍历
前序遍历:根左右
代码:
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode{
int val;
TreeNode *left;
TreeNode* right;
};
class Solution{
public:
void preorder(TreeNode* root,vector<int>&nums){
if(root == nullptr){
return;
}
nums.push_back(root->val);
preorder(root->left,nums);
preorder(root->right,nums);
}
vector<int>preorderTra(TreeNode*root){
vector<int>res;
preorder(root,res);
return res;
}
};
1.2、中序遍历
中序遍历:左根右
代码:
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode{
int val;
TreeNode *left;
TreeNode* right;
};
class Solution{
public:
void inorder(TreeNode* root,vector<int>&nums){
if(root == nullptr){
return;
}
inorder(root->left,nums);
nums.push_back(root->val);
inorder(root->right,nums);
}
vector<int>inorderTra(TreeNode*root){
vector<int>res;
inorder(root,res);
return res;
}
};
1.3、后序遍历
后序遍历:左右根
代码:
#include<iostream>
#include<vector>
using namespace std;
struct TreeNode{
int val;
TreeNode *left;
TreeNode* right;
};
class Solution{
public:
void postorder(TreeNode* root,vector<int>&nums){
if(root == nullptr){
return;
}
postorder(root->left,nums);
postorder(root->right,nums);
nums.push_back(root->val);
}
vector<int>postorderTra(TreeNode*root){
vector<int>res;
postorder(root,res);
return res;
}
};
二、由前+中重建二叉树
假设条件:遍历序列中无重复元素
由于前序遍历是根左右的顺序,可以由前序序列确定根结点的值,再在中序序列中确定根结点的位置,为什么要确定根结点位置呢,因为中序遍历是左根右的顺序,根结点即为左右子树的分界点,而后对左子树和右子树进行同样的操作,这就是一个递归的过程。
拿着根结点的值去中序序列中定位时,可以通过两种方法:
- 每次都用指针进行遍历;
- 将中序序列装进哈希表中,其中键为根结点的值,值为根结点在中序中的下标。
具体代码如下:
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x): val(x),left(nullptr),right(nullptr){}
};
class Solution{
private:
unordered_map<int,int>m;
public:
TreeNode* buildhelper(vector<int>&preorder,vector<int>&inorder,int preleft,int preright,int inleft,int inright){
if(preleft > preright){
return nullptr;
}
//在前序中确定根结点
int root_val = preorder[preleft];
//在中序中定位根结点
int root_index = m[root_val];
//建树
TreeNode* root = new TreeNode(root_val);
//左子树
root->left = buildhelper(preorder,inorder,preleft+1,root_index-inleft+preleft,inleft,root_index-1);
//右子树
root->right = buildhelper(preorder,inorder,root_index-inleft+preleft+1,preright,root_index+1,inright);
return root;
}
TreeNode* buildTree(vector<int>&preorder,vector<int>&inorder){
int num = inorder.size();
//哈希表存储中序序列,便于定位根结点
for(int i = 0; i < num; i++){
m[inorder[i]] = i;
}
return buildhelper(preorder,inorder,0,num-1,0,num-1);
}
};
三、由后+中重建二叉树
假设条件:遍历序列中无重复元素
和前+中同样的思路,具体代码如下:
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x): val(x),left(nullptr),right(nullptr){}
};
class Solution{
private:
unordered_map<int,int>m;
public:
TreeNode* buildhelper(vector<int>&postorder,vector<int>&inorder,int postleft,int postright,int inleft,int inright){
if(postleft > postright){
return nullptr;
}
//在后序中找到根结点
int root_val = postorder[postright];
//在中序中定位根结点
int root_index = m[root_val];
//建树
TreeNode* root = new TreeNode(root_val);
//左子树
root->left = buildhelper(postorder,inorder,postleft,root_index-inleft+postleft,inleft,root_index-1);
//右子树
root->right = buildhelper(postorder,inorder,root_index-inleft+postleft+1,postright-1,root_index+1,inright);
return root;
}
TreeNode* buildTree(vector<int>&postorder,vector<int>&inorder){
int num = inorder.size();
for(int i = 0; i < num; i++){
m[inorder[i]] = i;
}
return buildhelper(postorder,inorder,0,num-1,0,num-1);
}
};