数据结构之美--树(01)
1.重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回
思路:前序(根左右)遍历的第一个节点就是根节点,于是我们在中序(左根右)遍历中找到该节点,于是该节点就把树划分成了左子树和右子树,之后递归求解即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution
{
public:
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder)
{
auto pre_size = preorder.size();
auto in_size = inorder.size();
if (pre_size != in_size || pre_size == 0 || in_size == 0)
return nullptr;
return fun(preorder, 0, pre_size - 1, inorder, 0, in_size - 1);
}
TreeNode *fun(vector<int> &preorder, int preL, int preR,
vector<int> &inorder, int inderL, int inderR)
{
if (preL > preR)
return nullptr;
TreeNode *root = new TreeNode(preorder[preL]);
int i = 0;
for (; i <= inderR; i++)
{
if (inorder[i] == preorder[preL])
break;
}
int left_size = i - inderL;
int right_size = inderR - i;
root->left = fun(preorder, preL + 1, preL + left_size,
inorder, inderL, i - 1);
root->right = fun(preorder, preL + left_size + 1, preR,
inorder, i + 1, inderR);
return root;
}
};
4. 序列化二叉树
题目:实现两个函数,分别用来序列化和反序列化二叉树
题解:首先,前序遍历化为一个序列!
反序列化时,第一个就是root
,之后前半部分是左子树,后半部分是右子树,遇到一个’#'就得回到前面去找其
class Codec
{
public:
// Encodes a tree to a single string.
string serialize(TreeNode *root)
{
if (root == nullptr)
return "#";
return to_string(root->val) + "," + serialize(root->left) +","+ serialize(root->right);
};
// Decodes your encoded data to tree.
TreeNode *deserialize(string data)
{
return fun(data);
}
private:
TreeNode *fun(string &data)
{
if (data == "")
return nullptr;
if (data[0] == '#')
{
data = data.substr(data.find(',')+1);
return nullptr;
}
size_t idx=0;
int x = stoi(data,&idx);
data = data.substr(idx + 1);
TreeNode *root = new TreeNode(x);
root->left = fun(data);
root->right = fun(data);
return root;
}
};
这是最骚的:
class Codec {
private:
TreeNode* _root;
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
_root = root;
return string();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
return _root;
}
};
3. BST的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同
后序遍历(左右根).最后一个节点一定是整个树
的根节点,根据树与递归
的关系,泛化而讲,他会是树
的根节点(包括左子树,右子树等等).所以我们的思路就是先找到根,然后判断前部分(相当于左子树)是否小于根,后部分(相当于右子树)是否大于根
即可
class Solution
{
public:
bool VerifySquenceOfBST(vector<int> sequence)
{
int sz = sequence.size();
if (sz == 0)
return false;
return IsBST(sequence, 0, sz - 1);
}
//第一部分是左子树结点的值,它们都比根结点的值小
bool IsBST(const vector<int> &sequence, int left, int right)
{
if (left >= right)
return true;
int mid, tp = left;
int root = sequence.at(right);
/*先找左子树*/
while (tp < right && sequence.at(tp) < root)
{
tp++;
}
if (tp < right)
{
mid = tp;
//第二部分是右子树结点的值,它们都比根结点的值大
// 查找右子树是否符合要求
while (tp < right)
{
if (sequence.at(tp) < root)
{
return false;
}
tp++;
}
}
// 递归的判断左右子树是否符合要求
return IsBST(sequence, left, mid - 1) && IsBST(sequence, mid, right - 1);
}
};