/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (preorder.size() == 0) return nullptr;
int val = preorder[0];
vector<int> tempinorder_left;
vector<int> temppreorder_left;
vector<int> tempinorder_right;
vector<int> temppreorder_right;
for (int index = 0; index < inorder.size(); ++index) {
if (inorder[index] == val) {
for (int j = index + 1; j < inorder.size(); ++j) {
tempinorder_right.push_back(inorder[j]);
temppreorder_right.push_back(preorder[j]);
}
break;
} else {
tempinorder_left.push_back(inorder[index]);
temppreorder_left.push_back(preorder[index + 1]);
}
}
TreeNode *node = new TreeNode(val);
node->left = buildTree(temppreorder_left, tempinorder_left);
node->right = buildTree(temppreorder_right, tempinorder_right);
return node;
}
};
思路
最直观的方法,前序序列中的第一个为根节点,然后进行处理(创建两组前序、中序序列),将对应元素复制进去,分别递归;
但是开辟了额外的数组,时空效率极差;
解决方法:
使用两组游标标记两个端点,在递归中修改;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return MybuildTree(preorder, 0, preorder.size()-1, inorder, 0, inorder.size()-1);
}
TreeNode* MybuildTree(vector<int>& preorder, int pl, int pr, vector<int>& inorder, int il, int ir) {
if (pl > pr) return nullptr;
int val = preorder[pl];
int index = il;
while (inorder[index] != val) {
++index;
}
TreeNode *node = new TreeNode(val);
node->left = MybuildTree(preorder, pl+1, pl+index-il, inorder, il, index-1);
node->right = MybuildTree(preorder, pl+index-il+1, pr, inorder, index+1, ir);
return node;
}
};
要点
每次递归,得到节点为preorder[pl],并找到相应的中序遍历的下标位置(从il开始遍历);
找到小标之后,更新递归中的前、中序的左、右边界
——这里中序可以用index标识位置,前序需要用index-il作为偏移量标识位置(比较烧脑)
————————
还有一种只需要遍历一遍就得到结果的,把in、pre游标作为全局变量,每次递归的时候进行修改;用一个stop值(即preorder[pre]的值)指示每次递归的左右部分;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int pre = 0;
int in = 0;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return MybuildTree(preorder, inorder, INT_MAX);
}
TreeNode* MybuildTree(vector<int>& preorder, vector<int>& inorder, int stop) {
if (pre == preorder.size()) {
return nullptr;
}
if (inorder[in] == stop) {
++in;
return nullptr;
}
int val = preorder[pre++];
TreeNode *node = new TreeNode(val);
node->left = MybuildTree(preorder, inorder, val);
node->right = MybuildTree(preorder, inorder, stop);
return node;
}
};
pre、in为全局变量游标;
stop值为preorder[pre]值,也是inorder中分开左右子树的值;若inorder[in]为stop,说明该层递归左子树遍历完了,return null;该层右子树的stop值,是前一层的stop值;
INT_MAX——C++中的整型最大值;
该种方法必须确保树中的任意两个节点的值不相等;
真神仙解法,不多说了。。。