T3:
是的这道题并不是第一题,但是,这是今天收获较大的一道。关于通过二叉树先序遍历和中序遍历求出树的样子这件事,通过这道题,有了阶梯性的进步,得知了这个方法,对于以后的一系列此类问题,都可以用此方法进行举一反三;
思路:
通过先序遍历对树之中的根和子树的根一一求出进行辅助,再用中序遍历递归,找到一个根,由于是中序遍历,所以这个数的左边所有数都是它的左子树子孙节点,右边则是它右子树子孙节点,依照这个原则,递归下去,找到叶子节点都,递归上去与他的父节点建边,这样就可以递归建树了。
注意:
先序遍历依次排下来有可能出现当前范围内的根都被更新,从而找不到根的情况。这样以下的三行代码便可以较为完善的将其避免:
vis[b[pos]]=1;
while(vis[a[depth]]==1)depth++;
vis[b[pos]]=1;
#include<cstdio> #include<string> #include<cstring> using namespace std; struct Node{ int v,nxt; }tr[4010]; int Head[4010]; int kok=0; char a[2010]; char b[2010]; char val[2010]; int len; int root; int size[4010]; int ans[1000]; bool vv[4010]; bool vis[4010]; inline void add(int u,int v) { kok++; tr[kok].v=v; tr[kok].nxt=Head[u]; Head[u]=kok; } inline void qun(int l,int r,int depth,int fath)//开始递归建树 { if(l==r){//当l==r时,表明找到了一个最下面的叶子节点,直接建上并且标记方便输出答案 add(l,fath); add(fath,l); vv[l]=1; vis[b[l]]=1; val[l]=b[l]; return ; } while(vis[a[depth]]==1)depth++; int pos=0; for(int i=l;i<=r;i++){ if(a[depth]==b[i]){ pos=i; break; } } if(pos==0)return; if(depth==1)root=pos; qun(l,pos-1,depth+1,pos); qun(pos+1,r,depth+1,pos); if(fath!=0){ //递归完了就表明此节点的以下的节点都已经建立完毕,就将自己和fath建边 add(pos,fath); add(fath,pos); vis[b[pos]]=1; } val[pos]=b[pos]; } inline void dfs(int now,int fath) { //printf("%c\n",val[now]); size[now]=1;//求答案了 for(int i=Head[now];i;i=tr[i].nxt){ int v=tr[i].v; if(v==fath)continue; dfs(v,now); size[now]+=size[v]; } if(vv[now]!=1)size[now]--;//不为子节点要减一 } int main(void) { scanf("%s",a+1); scanf("%s",b+1); len=(int)strlen(a+1); qun(1,len,1,0); dfs(root,0); //for(int i=1;i<=len;i++)size[i]=size[i]>1?size[i]-1:size[i]; for(int i=1;i<=len;i++){ ans[(int)b[i]]=size[i]; } for(int i=1;i<=len;i++){ for(int j=1;j<=ans[(int)a[i]];j++){ printf("%c",a[i]); } printf("\n"); } } /* 123746895 327198564 abcgdfhie cbgaihefd */