前言:这两道题需要二叉树的知识(不会的可以去B站搜搜),需要画图,但博客里好像没有在线画图的功能,所以我只能写写大致的思路了
PS:二叉树遍历知二求一,但已知先后序遍历不行,需要额外的特殊条件来将左右子树分开
AC代码&思路:
#include<iostream>
#include<string>
using namespace std;
string zhong,hou;
void solve(int l1, int r1, int l2, int r2)
{
if(l1>r1) {return;}//说明已经递归到终点,直接结束
char root=hou[r2];//每个后序遍历的最后一个为当前子树的根
cout<<root;//前序遍历所有子树永远都是根左右的性质,到了最后一层可以看作它是下面虚拟子树的根
int pos;
for(pos=l1; pos<=r1; ++pos)
{
if(zhong[pos] == root) {break;}//从中序遍历中找到当前子树的根,确定他所在的位置
}
//利用左根右,再利用子树不同排列的长度不变解方程,即r2-l2==r1-l1
solve(l1, pos-1, l2, l2+pos-1-l1);//遍历左子树
solve(pos+1, r1, r2-r1+pos, r2-1);//遍历右子树
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>zhong>>hou;
int len=zhong.length();//中后序遍历长度不会变,写一次就行了
solve(0,len-1,0,len-1);//传入的相当于下标
return 0;
}
前言:把只有一个子结点的节点当作左子结点,这样前序遍历,左子树(根左右)当前区间的第二个节点一定是左子树的根节点
AC代码&思路:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int 二叉树节点数量
* @param pre intvector 前序序列
* @param suf intvector 后序序列
* @return intvector
*/
int len;
vector<int> qian;
vector<int> zhong;
vector<int> hou;
vector<int> solve(int n, vector<int>& pre, vector<int>& suf) {
//为了按照题解31的方式写递归函数,直接赋值给副本
qian=pre;hou=suf;len=n;
deal(0,len-1,0,len-1);
return zhong;
}
void deal(int l1,int r1,int l2,int r2)
{
if(l2>r2) {return;}//退出递归,避免出错,当pos==l2==r2时就会这样
else if(l2==r2) {zhong.emplace_back(hou[l2]);}//相当于上一题的cout,emplace_back是在当前的vector后添加元素
else
{
int root =qian[l1];
int pos;
for(pos=l2;pos<=r2;++pos)
{
if(hou[pos] == qian[l1+1]) {break;}//找左子树的根结点
}
//几乎跟上一题一模一样,这里是左根右的顺序
//还是利用r2-l2 == r1-l1解方程
deal(l1+1,pos-l2+l1+1,l2,pos);
zhong.emplace_back(root);
deal(r1-r2+pos+2,r1,pos+1,r2-1);
}
}
};