思路分析:
二叉树相关的很多问题的解决思路都有分治法的思想在里面。我们复习一下分治法的思想:把原问题拆解成若干个与原问题结构相同但规模更小的子问题,待子问题解决以后,原问题就得以解决
leetcode 106. 从中序与后序遍历序列构造二叉树
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
//如果当前数组元素为空,那么为空节点(这里写当前前序数组和当前后序数组都一样)
if (preorder.size() == 0)
return NULL;
//如果当前数组只剩一个元素,说明为叶子节点
if (preorder.size() == 1)
return new TreeNode(preorder[0]);
//构造当前根节点
TreeNode* root = new TreeNode(preorder[0]);
//通过pos索引找到中序数组中根的下标位置
int pos = 0;
for (int i = 0; i < inorder.size(); i++)
{
if (inorder[i] == preorder[0])
{
pos = i;
break;
}
}
//寻找当前左子树的根----需要将当前前序和中序数组部分的左子树部分打包进两个数组
//对左子树构成的二叉树,寻找当前二叉树的根
vector<int> p1(preorder.begin()+1, preorder.begin() + 1+pos);
vector<int> i1(inorder.begin(), inorder.begin() + pos);
root->left = buildTree(p1, i1);
//与上面同理,只不过变成寻找右子树的根
vector<int> p2(preorder.begin() + 1+pos, preorder.begin() + preorder.size());
vector<int> i2(inorder.begin()+pos+1, inorder.begin() +inorder.size());
root->right = buildTree(p2, i2);
//返回当前二叉树的根节点
return root;
}
};
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
int pSize = preorder.size();
int iSize = inorder.size();
return buildTree(preorder, inorder, 0, pSize - 1, 0, iSize - 1);
}
//pBegin和pEnd分别是当前前序数组的起点和终点 iBegin和iEnd分别是当前中序数组的起点和终点
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder, int pBegin, int pEnd, int iBegin, int iEnd)
{
//如果指针错位,说明当前位空节点
if (pBegin > pEnd || iBegin > iEnd)
return NULL;
//构造当前根节点---当前前序数组的起点
TreeNode* root = new TreeNode(preorder[pBegin]);
//寻找根节点在当前中序数组的下标位置
int pos = 0;
while (preorder[pBegin] != inorder[pos])
pos++;
//寻找当前左子树根节点
root->left = buildTree(preorder, inorder, pBegin + 1, pBegin + pos - iBegin,
iBegin, pos - 1);
//寻找当前右子树的根节点
root->right = buildTree(preorder, inorder, pEnd - iEnd + pos + 1, pEnd,
pos + 1, iEnd);
return root;
}
};
class Solution {
vector<int> preorder;
unordered_map<int, int> map;
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
{
int pSize = preorder.size();
int iSize = inorder.size();
this->preorder = preorder;
for (int i = 0; i < iSize; i++)
map[inorder[i]] = i;
return buildTree(0, pSize - 1, 0, iSize - 1);
}
//pBegin和pEnd分别是当前前序数组的起点和终点 iBegin和iEnd分别是当前中序数组的起点和终点
TreeNode* buildTree(int pBegin, int pEnd, int iBegin, int iEnd)
{
//如果指针错位,说明当前位空节点
if (pBegin > pEnd || iBegin > iEnd)
return NULL;
//构造当前根节点---当前前序数组的起点
TreeNode* root = new TreeNode(preorder[pBegin]);
//寻找根节点在当前中序数组的下标位置
int pos = map[preorder[pBegin]];
//寻找当前左子树根节点
root->left = buildTree(pBegin + 1, pBegin + pos - iBegin,
iBegin, pos - 1);
//寻找当前右子树的根节点
root->right = buildTree( pEnd - iEnd + pos + 1, pEnd,
pos + 1, iEnd);
return root;
}
};