1119. Pre- and Post-order Traversals (30)

来源:互联网 发布:河南坠子乎延庆打擂 编辑:程序博客网 时间:2024/06/11 07:19

本来以为自己对二叉树很熟悉的。
结果写了半天还是写不出来,只能网上学习别人的代码
唉感觉自己很菜,嘤嘤嘤。

先分析本题的算法。
给前序和后序,求任意中序并判断中序是否唯一。
那么中序或者说这棵二叉树是否唯一,究竟是看什么呢?
4
1 2 3 4
2 4 3 1
从示例中我们分析一下前序是根左右,后序是左右根
那么我们可以参照前中序。
前序的根的后一个是左子树(或者没有左子树,那就是右子树)的根
那么在后序中查找,找到的那个位置一直到查找的起点,这段距离就是左子树的长度。
例如;
1 2 34
2 43 1
我是为什么这么分的呢,首先,1自然是root,那么在后序里面找2,发现起始点到2的长度只有1
那么也就是说,root的左子树,只有1个节点。那么 剩下的34必然是右子树啦。
递归下去我们再来看34
对于34,3必然是root,那么在后序(43)里面找4,也就是以3为root的左子树树根
找到了,并且发现左子树大小为1,那么继续往后看,发现没了。
那么这个4,究竟是左子树还是右子树呢?
无从得知。
故从sample中得知,如果对于一个root,他的左子树和右子树都存在,那么一直到检查到这个节点。他一直都可以是唯一的。但是如果递归到一个root,它只有一段子树。例如这个讲到的34和43,那么我们就不知道了。故从这个点来设计算法。
并且题目中要求输出任意一个二叉树。
那么我们就规定死,如果一个root只有一个儿子,那么就定死他是左儿子,或者是右儿子,那么久可以找到其中的一棵树了。
贴代码:
(参考网上的代码的)

#include <bits/stdc++.h>using namespace std;int num1[31], num2[31], re[31];bool res = true;int Index;int n;void check(int l1,int r1,int l2,int r2){  if (l1 > r1)//也就是说,当前dfs到的root只有一个儿子  {    res = false;    return;  }  else if (l1 == r1)//为什么这里要提前return,而不是像正常那样中序递归遍历呢?  {                 //原因在于我们的判断方式是看会不会有一次的dfs,l1比r1还大    re[Index++] = num1[l1];//如果这里不提前return,那么下次遍历的时候,l1一定大于r1,res就为false了    return;//所以这里提前return,并且记录  }  int i;  for (i = l2; i <= r2; i++)  {    if (num2[i] == num1[l1+1]) break;  }  check(l1+1, l1+1+i-l2, l2, i);//往左dfs  re[Index++] = num1[l1];//中序记录  check(l1+2+i-l2, r1, i+1, r2-1);//往右dfs}int main(void){  cin >> n;  int i;  for (i = 0; i < n; i++)  {    cin >> num1[i];  }  for (i = 0; i < n; i++)  {    cin >> num2[i];  }  check(0, n - 1, 0, n - 1);  if (!res)   {    cout << "No" << endl;  }  else cout << "Yes" << endl;  for (i = 0; i < n - 1; i++)  {    cout << re[i] << " ";  }  cout << re[i] << endl;}

想要心里有点树,我还是得继续努力啊
加油!

原创粉丝点击