PAT A1138 Postorder Traversal
Sample Input:
7
1 2 3 4 5 6 7
2 3 1 5 4 7 6
Sample Output:
3
-
思路 1:静态树版
建树,后序遍历–》麻烦 -
code 1:
#include <vector>
#include <iostream>
using namespace std;
const int maxn = 50010;
int preo[maxn], ino[maxn], idex;
struct Node{
int data, lc, rc;
}node[maxn];
int newNode(int x){
idex++;
node[idex].data = x;
node[idex].lc = -1;
node[idex].rc = -1;
return idex;
}
int create(int preL, int preR, int inL, int inR){
if(preL > preR) return -1;
int r = newNode(preo[preL]);
int idex = inL;
while(idex <= inR && ino[idex] != preo[preL])idex++;
int numL = idex - inL;
node[r].lc = create(preL+1, preL+numL, inL, idex-1);
node[r].rc = create(preL+numL+1, preR, idex+1, inR);
return r;
}
int cnt = 0;
void postOrder(int r){
if(r == -1) return;
if(node[r].lc != -1) postOrder(node[r].lc);
if(node[r].rc != -1) postOrder(node[r].rc);
if(cnt++ == 0)
printf("%d", node[r].data); //!!!Wrong 1:输出的是node[r].data 不是r r只是一个指针
}
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", &preo[i]);
}
for(int i = 0; i < n; ++i){
scanf("%d", &ino[i]);
}
int root = create(0, n-1, 0, n-1);
postOrder(root);
return 0;
}
- 思路 2:建树 指针版
- code 2:
#include <vector>
#include <iostream>
using namespace std;
const int maxn = 50010;
int preo[maxn], ino[maxn], idex;
struct node{
int data;
node *lc, *rc;
};
node* newNode(int x){
node* root = new node;
root->data = x;
root->lc = root->rc = NULL;
return root;
}
node* create(int preL, int preR, int inL, int inR){
if(preL > preR) return NULL;
node* r = newNode(preo[preL]);
int idex = inL;
while(idex <= inR && ino[idex] != preo[preL])idex++;
int numL = idex - inL;
r->lc = create(preL+1, preL+numL, inL, idex-1);
r->rc = create(preL+numL+1, preR, idex+1, inR);
return r;
}
int cnt = 0;
void postOrder(node* root){
if(root == NULL) return;
if(root->lc != NULL) postOrder(root->lc);
if(root->rc != NULL) postOrder(root->rc);
if(cnt++ == 0)
printf("%d", root->data); //!!!Wrong 1:输出的是node[r].data 不是r r只是一个指针
}
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i){
scanf("%d", &preo[i]);
}
for(int i = 0; i < n; ++i){
scanf("%d", &ino[i]);
}
node* root = create(0, n-1, 0, n-1);
postOrder(root);
return 0;
}
- 思路 3:直接前序中序转后序:
后序遍历本质就是左不空递归的访问左,右不空访问右,最后访问根:
用前序和中序每次都可以分出左子树和右子树
#include <iostream>
using namespace std;
const int maxn = 50010;
int n, preo[maxn], ino[maxn], cnt = 0;
void postOrder(int preL, int inL, int inR){
if(inL > inR || cnt) return; //增加递归返回条件cnt,减少时间
int idex = inL;
while(ino[idex] != preo[preL]) idex++;
postOrder(preL+1, inL, idex-1);
postOrder(preL+idex-inL+1, idex+1, inR);
if(cnt++ == 0) printf("%d", preo[preL]);
}
int main(){
scanf("%d", &n);
for(int i = 0; i < n; ++i) scanf("%d", &preo[i]);
for(int i = 0; i < n; ++i) scanf("%d", &ino[i]);
postOrder(0, 0, n-1);
return 0;
}
- T2 code: 用一个bool型变量first控制,只取后序第一个元素,其他直接跳过
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50010;
int seq[2][maxn];
bool first = true;
void Create(int preL, int preR, int inL, int inR){
int r = seq[0][preL], idex = inL;
while(idex < inR && seq[1][idex] != r) idex++;
int numL = idex - inL, numR = inR - idex;
if(numL > 0) Create(preL + 1, preL + numL, inL, idex - 1);
if(numR > 0) Create(preL + numL + 1, preR, idex + 1, inR);
if(first){
printf("%d", r);
first = false;
}
}
int main(){
int n;
scanf("%d", &n);
for(int i = 0; i < 2; ++i){
for(int j = 0; j < n; ++j){
scanf("%d", &seq[i][j]);
}
}
Create(0, n - 1, 0, n - 1);
return 0;
}
- T3 code:
#include <bits/stdc++.h>
using namespace std;
vector<int> pre, in;
bool flg = true;
void Create(int preL, int preR, int inL, int inR)
{
if(preL >= preR || flg == false) return;
int r = pre[preL], id = inL;
while(id < inR && in[id] != r) id++;
int numL = id - inL;
Create(preL+1, preL+1+numL, inL, id);
Create(preL+1+numL, preR, id+1, inR);
if(flg)
{
printf("%d", r);
flg = false;
}
}
int main()
{
int n;
scanf("%d", &n);
pre.resize(n); in.resize(n);
for(int i = 0; i < 2; ++i)
{
for(int j = 0; j < n; ++j)
{
if(i == 0) scanf("%d", &pre[j]);
else scanf("%d", &in[j]);
}
}
Create(0, n, 0, n);
return 0;
}
- T4 code:
#include <bits/stdc++.h>
using namespace std;
vector<int> pre, in;
unordered_map<int, int> post_in;
void Create(int preL, int preR, int inL, int inR, bool & flg)
{
if(preL >= preR || flg) return;
int r = pre[preL], id = post_in[r], numL = id - inL;
Create(preL+1, preL+1+numL, inL, inL+numL, flg);
Create(preL+1+numL, preR, inL+numL+1, inR, flg);
if(flg == false)
{
printf("%d", r);
flg = true;
}
}
int main()
{
int n;
scanf("%d", &n);
pre.resize(n); in.resize(n);
for(int i = 0; i < n; ++i)
{
scanf("%d", &pre[i]);
}
for(int i = 0; i < n; ++i)
{
scanf("%d", &in[i]);
post_in[in[i]] = i;
}
bool flg = false;
Create(0, n, 0, n, flg);
return 0;
}
- 可以用exit(),强行退出递归
void Create(int preL, int preR, int inL, int inR)
{
if(preL >= preR) return;
int r = pre[preL], id = post_in[r], numL = id - inL;
Create(preL+1, preL+1+numL, inL, inL+numL);
Create(preL+1+numL, preR, inL+numL+1, inR);
printf("%d", r);
exit(0);
}