Leetcode 105 & 106
Quetion 105
Given preorder and inorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
Quetion 106
Given inorder and postorder traversal of a tree, construct the binary tree.
Note:
You may assume that duplicates do not exist in the tree.
这两道题类似,都是根据树的遍历来重建一棵树。
先复习下先序中序后序:先序根左右,中序左根右,后序左右根,区别是根的出现的顺序。一开始想着用传vector的方法,但是后来发现内存爆了,用索引的方法更好, 因为只遍历了一次整个vector所以时间复杂度为O(n)
说下105即根据先序中序遍历来重建一棵树的做法:因为先序的第一个元素是根,然后在中序遍历中找到这个根。然后在中序的遍历元素中,根左边的那些元素是根的左子树,右边是右子树,然后根据左右子树的长度在前序中区分出左右子树,继续往下建树。比较难的一点就在于区分出这个边界。代码如下:
class Solution {
public:
TreeNode* createNode(vector<int>& preOrder, vector<int>& inOrder, int startPre, int endPre, int startIn, int endIn) {
if (startPre > endPre || startIn > endIn)
return NULL;
int root = preOrder[startPre], index;
for (index = startIn; index <= endIn; index++) {
if (inOrder[index] == root)
break;
}
TreeNode* res = new TreeNode(root);
res->left = createNode(preOrder, inOrder, startPre + 1, startPre + 1 + (index - 1 - startIn), startIn, index - 1);
res->right = createNode(preOrder, inOrder, startPre + 1 + (index - startIn), endPre, index + 1, endIn);
return res;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
TreeNode* res = createNode(preorder, inorder, 0, preorder.size() - 1, 0, preorder.size() - 1);
return res;
}
};
106是根据后序中序来重建一棵树,过程相似,后序遍历的最后一个元素是根,然后在中序中找出这个根,中序中根的左边是左子树,右边是右子树,然后相似的重建这棵树,同样要区分出边界,代码如下:
class Solution {
public:
TreeNode* createNode(vector<int>& inorder, vector<int>& postorder, int startIn, int endIn, int startPost, int endPost) {
if (startIn > endIn || startPost > endPost) {
return NULL;
}
// 后序的最后一个表示的是根节点
int root = postorder[endPost], index = startIn;
TreeNode* p = new TreeNode(root);
for (index; index <= endIn; index++) {
if (inorder[index] == root) {
break;
}
}
p->left = createNode(inorder, postorder, startIn, index - 1, startPost, startPost + index - 1 - startIn);
p->right = createNode(inorder, postorder, index + 1, endIn, endPost - 1 - (endIn -index - 1), endPost - 1);
return p;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
TreeNode* res;
res = createNode(inorder, postorder, 0, inorder.size() - 1, 0, postorder.size() - 1);
return res;
}
};
最后贴个别人写的一个更好的代码,思路相似,但是是先建好右子树,然后index不断移动,再到建立左子树:
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.empty() || postorder.empty())
return NULL;
int root_index = postorder.size()-1;
return createBST(inorder,postorder,0,root_index,root_index);
}
TreeNode* createBST(vector<int>& inorder, vector<int>& postorder, int start, int end, int& index) {
int v = postorder[index];
int i = end;
for (i; i >= start; i--)
if (inorder[i] == v)
break;
TreeNode* root = new TreeNode(v);
if (end >= i+1)
root->right = createBST(inorder,postorder,i+1,end,--index);
if (i-1 >= start)
root->left = createBST(inorder,postorder,start,i-1,--index);
return root;
}
};