写完这道题之后,你对树的理解应该会更加深刻
按中序遍历和后序遍历给出一棵二叉树,求这棵二叉树中叶子节点权值的最小值。
输入保证叶子节点的权值各不相同。
第一行输入一个整数t,表示有t组测试数据。
对于每组测试数据,首先输入一个整数N (1 <= N <= 10000),代表二叉树有N个节点,接下来的一行输入这棵二叉树中序遍历的结果,最后一行输入这棵二叉树后序遍历的结果。
对于每组测试数据,输出一个整数,代表二叉树中叶子节点权值最小值。
3
7
3 2 1 4 5 7 6
3 1 2 5 6 7 4
8
7 8 11 3 5 16 12 18
8 3 11 7 16 18 12 5
1
255
255
1
3
255
如果你急着要代码,可以先把代码复制了,但是main函数请自己写,哈哈哈哈哈哈哈哈哈哈
如果你不急,那么请听我细细道来
#include
#include
#include
using namespace std;
const int maxn = 1e6;
int post[maxn];
int ino[maxn];
int n, ans;
int cnt;
void init()
{
ans = 0x7fffffff;
cin >> n;
for (int i = 0; i < n; i++)
scanf("%d", ino + i);
for (int i = 0; i < n; i++)
scanf("%d", post + i);
}
int find(int l,int r,int num)
{
for (int i = l; i < r; i++)
{
if (num == ino[i])
return i;
}
return -1;
}
void solve(int l, int r, int root)
{
if (r <= l)
return;
if (l + 1 == r)
{
ans = min(ans, ino[l]);
return;
}
int mid = find(l,r,post[root]);
solve(mid + 1, r, root - 1);
solve(l, mid, root-(r-mid));
}
int main()
{
// 请自己写
return 0;
}
题目的只给了我们中序遍历和后序遍历的树,让我们通过这两个遍历找出所有叶子节点
对此我们先来讲讲建树
现在有一棵树,它长这样
那么这颗树的
中序遍历是这样213
后序遍历是这样231
对这颗树拓展一下就是
对所有可能的树
中序遍历是这样(左子树)(根节点)(右子树)
后序遍历是这样(左子树)(右子树)(根节点)
由此,我们可以发现,一颗树的后序遍历的最后一个节点,必定是那颗树的根节点root
然后我们可以通过那个根节点,在中序遍历里找到根节点的位置mid,
这样左子树在中序遍历中的位置就是[l,mid-1]
,
右子树在中序遍历中的位置就是[mid+1,r]
对于这个在中序遍历里找到根节点位置,我们写了一个函数
int find(int l,int r,int num)
{
// l 就是中序遍历的那棵树的左边边界
// r 就是中序遍历的那棵树的右边边界
for (int i = l; i < r; i++)
{
if (num == ino[i])
return i;
}
return -1;
}
但是我们找到了中序遍历的左子树和右子树又有什么用呢?
我们来回顾一下题目要我们求什么,求叶子节点的最小值,也就是说找到所有叶子节点,
什么是叶子节点?没有左子树,没有右子树!
那么那棵树应该长这样
void solve(int l, int r, int root)
{
// 要理清这三个参数的含义
// l,r 是针对中序遍历的
// 在[l,r) 中找一颗树
// root 是针对后序遍历的,存储的是后序遍历中当前这棵树的最后一个节点
if (r <= l) // 不合法的树
return;
if (l + 1 == r) // 树里只有一个根节点,那么就是叶子
{
ans = min(ans, ino[l]); // 更新答案,找到最小的叶子
return;
}
// 树里不止一个节点
int mid = find(l,r,post[root]); // 找到根节点在中序遍历中的位置
solve(mid + 1, r, root - 1); // 找右子树
solve(l, mid, root-(r-mid)); // 找左子树
}
可能有的同学会问,为什么是root-1?为什么是root-(r-mid)?
root 代表的是当前树在后序遍历中的最后一位
所以对于当前树的右子树,右子树在后序遍历中的最后一位就是root-1
,也就是前一位
通过观察我们可以发现,左子树在后序遍历中的最后一位与当前root之间相差了一个右子树的长度
那么我们可以由中序遍历的r-mid得到右子树的长度,所以左子树在后序遍历中的最后一位就是root-(r-mid)
感谢各位的愿意看到这里,我知道写的很烂,但是我已经在练习怎么写的更好了
在此献上我的main函数
int main()
{
// freopen("in.txt", "r", stdin);
int t;
cin >> t;
while (t--)
{
init();
solve(0, n, n - 1);
printf("%d\n", ans);
}
return 0;
}