近日我练习PAT的时候做到这道题,其实思路并不难,我大概理解就是通过Push和Pop组合建树的一个过程(也可以理解为根据先序和中序来输出后序遍历的过程)。但是就是过不了测试点0和测试点4,特别古怪的就是测试点1,明明在我的编译器上输入根本就没有任何问题,提交到PTA系统就显示答案错误(甚至还出现过段错误的提示)。如图所示:
测试点 | 提示 | 结果 | 耗时 | 内存 |
---|---|---|---|---|
0 | sample 有单边有双边结点 | 答案错误
| 1 ms | 256 KB |
1 | 单边喇叭张开形 | 答案正确
| 3 ms | 384 KB |
2 | 交错 | 答案正确
| 2 ms | 384 KB |
3 | N=1 | 答案正确
| 2 ms | 256 KB |
4 | N=30,复杂组合 | 答案错误
| 2 ms | 256 KB |
于是翻遍全网只找到了别人的提问和AC的代码,并没有找到错误的原因究竟在哪,最后研究了一下午终于发现这道题的阴险之处:
这是这道题给的示例图:
这是这道题给的Sampl Input:
6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop
问题就在于:其实测试点0的数据和这里输入的数据根本就不一样!虽然说树和示例图给的树是一样的,Push和Pop序列也和题目给的序列是一样的,但是测试用例把结点的编号给换了!也就是,这道题目并没有说第一次一定要Push 1,我也可以第一次Push 2,这样一来2就变成了这棵树的根节点。如果你的算法也和我一样,根据输入的数字是否是1来判断是否是根节点的话,那就会出现测试点0和测试点4不通过的情况!
解决方法:解决方法也很简单,设置一个计数器cnt = 0,每次Push的时候cnt自增,把第一次的时候Push的节点设置为根节点,这样就通过啦!
测试点 | 提示 | 结果 | 耗时 | 内存 |
---|---|---|---|---|
0 | sample 有单边有双边结点 | 答案正确
| 2 ms | 364 KB |
1 | 单边喇叭张开形 | 答案正确
| 3 ms | 376 KB |
2 | 交错 | 答案正确
| 2 ms | 288 KB |
3 | N=1 | 答案正确
| 3 ms | 256 KB |
4 | N=30,复杂组合 | 答案正确
| 2 ms | 256 KB |
我的代码其实写的很乱而且没有注释,但考虑到有些朋友需要参考一下,我就把我AC的代码贴上来吧:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node{ //定义树
int no;
struct Node *left;
struct Node *right;
int time;
}Node;
typedef struct Node* Tree;
Tree BuiltTree(int n); //建树并返回头结点地址
Tree CreateNode(int no); //建立节点并返回地址
void PostTravesal(Tree bt); //后序遍历
int tik = 0;
int main(void)
{
int n;
scanf("%d", &n);
if ( n ) //如果是空树直接返回
{
Tree bt = BuiltTree(n);
PostTravesal(bt);
}
return 0;
}
Tree BuiltTree(int n)
{
Tree stack[n], bt, T;
int top = -1;
int i, cnt = 0;
char str[5];
int no, flag = 0;
while ( 1 )
{
getchar();
scanf("%s", str);
if ( strcmp(str, "Push") == 0 ) //如果输入的是Push
{
++cnt; //计数器自增
scanf(" %d", &no);
if ( cnt == 1 ) //头结点特殊处理
{
T = CreateNode(no);
bt = T;
stack[++top] = T;
}
else
{
if ( T->time == 1 ) //time用于判断T指向结点是刚Push的还是刚Pop的
{
T->left = CreateNode(no);
T = T->left;
stack[++top] = T;
}
else //time为2就说明是Pop出来的节点故放右孩子
{
T->right = CreateNode(no);
T = T->right;
stack[++top] = T;
}
}
if ( cnt == n )
flag = 1;
}
else if ( strcmp(str, "Pop") == 0 ) //Pop之后把time设置为2
{
T = stack[top--];
T->time = 2;
}
if ( flag == 1 && top == -1 ) //当最后一个节点也被Push了而且栈空了
break;
}
return bt;
}
Tree CreateNode(int no)
{
Tree bt = (Tree)malloc(sizeof(Node));
bt->no = no;
bt->left = NULL;
bt->right = NULL;
bt->time = 1;
return bt;
}
void PostTravesal(Tree bt)
{
if ( bt )
{
PostTravesal(bt->left);
PostTravesal(bt->right);
if ( tik!= 0 )
putchar(' ');
printf("%d", bt->no);
tik = 1;
}
}