题目:http://acm.hdu.edu.cn/showproblem.php?pid=3791
直接的方法即可0ms通过,没有什么弯:
#include <cstdio>
#include <cstring>
struct Node{
int val;
Node* left;
Node* right;
};
int index = 0;
Node arr[20];
Node* newNode(int v)
{
arr[index].val = v;
arr[index].left = arr[index].right = NULL;
return &arr[index++];
}
void insertBST(Node*& root, int v)
{
if(root == NULL){
root = newNode(v);
return;
}
if(root->val > v) insertBST(root->left, v);
else insertBST(root->right, v);
}
bool isEqual(const Node* p, const Node* q)
{
if(p == NULL) return q == NULL;
else if(q == NULL || p->val != q->val) return false;
else return isEqual(p->left, q->left) && isEqual(p->right, q->right);
}
void buildBST(Node*& root, char* s)
{
root = NULL;
for(; *s; ++s) insertBST(root, *s - '0');
}
int main()
{
int n, i, len;
char s[12];
Node *p, *q;
while(scanf("%d", &n), n){
while(getchar() != '\n') ;
//initialize
index = 0;
//build source tree
len = strlen(gets(s));
buildBST(p, s);
//build each target tree and compare
while(n--){
index = len;
if(len != strlen(gets(s))){
puts("NO");
continue;
}
buildBST(q, s);
if(isEqual(p, q)) puts("YES");
else puts("NO");
}
}
return 0;
}
我们可以看到不同的序列直接插入构造的话可能形成相同的二叉搜索树,那么有一个问题了,给出一个二叉搜索树,到底对应了多少个不同的序列呢:
事实上,我们可以看到,只要我们保证每棵子树的根节点比左右节点先插入到二叉搜索树里,就能在改变其他节点插入顺序后仍然使整棵树的结构不变。
那么给出一颗有N个节点的二叉搜索树,到底它能由多少个序列直接插入构成呢?
以题目给的例子为例,我们只要保证5->4->3->2且5->6->7的拓扑顺序就能构成相同结构的二叉搜索树,所以实际上我们要解决的问题是求一个拓扑树遍历的全部可能性:
int howManyInsertingSequences(const Node* root)
{
if(root == NULL) return 0;
if(root->left == NULL && root->right == NULL) return 1;
vector<const Node*> nodeSet, path;
set<const Node*> visited;
nodeSet.push_back(root);
return backtrace(nodeSet, visited, path);
}
int backtrace(vector<const Node*>& nodeSet,
set<const Node*>& visSet,
vector<const Node*>& path)
{
if(visSet.size() == nodeSet.size()){
for(int i = 0, n = path.size(); i < n; ++i) printf("%d ", path[i]->val);
puts("");
return 1;
}
int total = 0;
for(int i = 0, n = nodeSet.size(); i < n; ++i){
const Node* p = nodeSet[i];
if(visSet.count(p)) continue;
//forward
visSet.insert(p);
path.push_back(p);
if(p->left != NULL) nodeSet.push_back(p->left);
if(p->right != NULL) nodeSet.push_back(p->right);
total += backtrace(nodeSet, visSet, path);
//rewind
if(p->right != NULL) nodeSet.pop_back();
if(p->left != NULL) nodeSet.pop_back();
path.pop_back();
visSet.erase(p);
}
return total;
}