🍄前言
大家好哇,我是一勺黑猫,可以叫我小勺。今天是每日一题的第十二天,欢迎更多小伙伴加入到我们的打卡计划中,希望和你们在学习算法的路上一起进步~
🙎作者简介:一个正在努力学算法和后端的大三girl
⏳每日一题打卡地:高校算法学习社区
🎈联系方式:157543570(qq)
💨往期请看:小勺的每日一题
https://blog.csdn.net/xingziyy/category_11731303.html
🍄今日题目
P1827 [USACO3.4] 美国血统 American Heritage - 洛谷 | 计算机科学教育新生态
🌰思路:本题用到树的前序中序转后序算法。假设你已经知道怎么由前序中序构建一棵二叉树,并后序遍历这棵树。那怎么用算法实现呢?
实际上,我们不需要创建出二叉树再遍历,而是通过递归直接输出就好了。我们需要一个函数post(int index,int l,int r),其中index表示每次遍历的根节点在前序序列中的位置,l和r表示遍历中序序列的范围。
初次遍历时,我们应该让index=0,l=0,r=in.length()-1,因为前序序列的第一个元素 是整棵树的根节点,遍历范围是整颗二叉树,如下图:
函数中要做什么呢?由于后序遍历是左、右、根的顺序,所以我们应该先递归调用此函数,分别遍历左子树和右子树,最后输出根节点的值。
基于此,我们的任务就是找到函数的参数:左右子树的根节点及其范围。
根据下图,我们容易发现,如果找到根节点在中序序列中的位置i,就可以确定树的左子树和右子树的范围:[l,i-1],[i+1,r]。同样的,可以发现,在前序序列中,左子树的根节点是index+1,右子树的根节点是index+(i-l)+1。找到这些信息,我们就可以遍历左右子树啦(如果记不住范围的话,不妨在写代码时画一画,就不用死记硬背了~)
还有一点需要注意的是函数的结束条件。当l>r时,说明当前子树是空树,直接返回就好了。
🌰AC代码:
#include<iostream>
using namespace std;
//中序和前序序列
string in,pre;
void post(int index,int l,int r){
if(l>r)
return;
//查找前序根节点在中序中的位置
int i=l;
while(i<r&&in[i]!=pre[index]) i++;
post(index+1,l,i-1); //左子树
post(index+i-l+1,i+1,r); //右子树
cout<<pre[index]; //输出根
}
int main(){
cin>>in>>pre;
post(0,0,in.length()-1);
return 0;
}
第一次画图用的ps,着实费了好大的劲qaq,如果有好用的画图软件可以推荐给我😘
看完如果让你有一丝收获,球球给一个三连支持!!!感谢大家