PTA:L2-006 树的遍历
题意:中序遍历+后序遍历=>层次遍历
题解:
- 由算法可知,每次找到后序遍历的最后一个元素即post[pos],从中序遍历中找到in[mid] = post[post],mid划分树。
- 如果按照父节点和儿子结点的关系为2*parent=son,那么数组要开2^n,为了节省空间,不按照此编号。定义全局变量id,dfs返回的是子节点的编号,如果不存在则为-1。
#include
using namespace std;
int const N = 30 + 5;
int post[N],in[N],n,pos,id;
vectorans;
struct Node{
int l,r,val;
}node[N];
int dfs(int l,int r){
if(l > r)return -1;
//返回id
int mid = 0;
for(int i=l;
i<=r;
i++){
if(in[i] == post[pos]){
mid = i;
break;
}
}
int tid = ++id;
node[tid].val = post[pos--];
node[tid].r = dfs(mid + 1,r);
node[tid].l = dfs(l,mid - 1);
return tid;
}
void level_dfs(){
queueq;
q.push(1);
while(!q.empty()){
int p = q.front();
q.pop();
ans.push_back(node[p].val);
if(node[p].l != -1) q.push(node[p].l);
if(node[p].r != -1) q.push(node[p].r);
}
for(int i=0;
i
PTA:L2-011 玩转二叉树
题意:中序遍历+前序遍历=>反转层次遍历
题解:
- 思路同上。pos从1开始递增。
- 层次遍历先考虑右子树,再考虑左子树。
#include
using namespace std;
int const N = 30 + 5;
int pre[N],in[N],n,pos,id;
vectorans;
struct Node{
int l,r,val;
}node[N];
int dfs(int l,int r){
if(l > r)return -1;
//返回id
int mid = 0;
for(int i=l;
i<=r;
i++){
if(in[i] == pre[pos]){
mid = i;
break;
}
}
int tid = ++id;
node[tid].val = pre[pos++];
node[tid].l = dfs(l,mid - 1);
node[tid].r = dfs(mid + 1,r);
return tid;
}
void level_dfs(){
queueq;
q.push(1);
while(!q.empty()){
int p = q.front();
q.pop();
ans.push_back(node[p].val);
if(node[p].r != -1) q.push(node[p].r);
if(node[p].l != -1) q.push(node[p].l);
}
for(int i=0;
i
PTA:1119Pre- and Post-order Traversals
题意:由前序和后序构造中序遍历,不唯一输出任意一个
题解:
- 当存在结点只有左子树或者右子树,前序和后序相同,所以不能保证唯一。但是无论是左子树还是右子树对中序遍历的结果并不影响。
- 【l1,r1】为前序遍历的区间,【l2,r2】为后序遍历的区间
- 前序遍历的第一个和后序遍历的最后一个必定相同,即pre[l1] = post[r2],且为根节点root。
- 那么post[r2-1]可能是root的右儿子(结果不唯一时,也有可能是左儿子,我们这里假设是右儿子),在前序遍历数组中找到pre[mid] = post[r2-1],根据前序遍历的特性,易知【l1+1,mid - 1】是root的左子树,其对应的后序遍历区间为【l2,l2 + lson - 1】,lson = (mid - 1) - (l1 + 1) + 1为左子树的大小。
- 同理【mid,r1】为右子树,其对应的后序遍历区间为【l2 + lson,r2 - 1】。
- 当出现lson为0,表示结果不唯一,post[r2-1]可能是左儿子,但是我们默认是右儿子,所以步骤二可这样解释。
#include
using namespace std;
int const N = 30 + 5;
int pre[N],post[N];
int n,flag;
vectorans;
void solve(int l1,int r1,int l2,int r2){
if(l1 == r1){
ans.push_back(pre[l1]);
return;
}
int mid;
for(int i=l1+1;
i<=r1;
i++){
if(pre[i] == post[r2-1]){
mid = i;
break;
}
}
int lson = (mid - 1) - (l1 + 1) + 1;
if(lson >= 1)
solve(l1 + 1,mid - 1,l2,l2 + lson - 1);
else
flag = false;
ans.push_back(pre[l1]);
solve(mid,r1,l2 + lson,r2 - 1);
}
int main(){
scanf("%d",&n);
for(int i=1;
i<=n;
i++)
scanf("%d",&pre[i]);
for(int i=1;
i<=n;
i++)
scanf("%d",&post[i]);
flag = true;
solve(1,n,1,n);
if(flag)printf("Yes\n");
elseprintf("No\n");
for(int i=0;
i
【PTA|二叉树前序、中序、后序、层次遍历之间的转换】
推荐阅读
- #|7-7 约瑟夫问题变形 (10 point(s))
- 基础算法模板总结|离散化 算法 思路+模板代码
- 数据结构|单调栈与单调队列
- 数据结构|数组模拟栈与队列
- 数据结构|并查集详解
- 数据结构|离散化算法
- 算法|学会二叉树不知道干啥?二叉树的深度优先搜索和广度优先搜索,我要打十个乃至二十个(打开你的LeetCode撸起来)学练并举
- python|算法的时间复杂度
- 数据结构|Lambda 表达式 - java - 细节狂魔