题目大意:
给你一棵二叉树的中序遍历和后序遍历,让你找从根到叶子结点的路径最短的叶子结点,如果有多个路径符合,就选择叶子结点最小的结点。
然而题意看错两次。。。。。。第一次以为只找值最小的叶子结点,第二次以为选择第一次出现的最短路径。。。。。。注意以后看题时不要通过input,output来推测题意。而是在把前言理解的基础上,再看题。题目错了就呵呵了。
思路:
因为题目只要求解出结果,便不需要实际建树,只是模拟建树即可,用两个变量p1,p2限制后序遍历的树的左右界限,in1,in2来限制中序遍历树的左右界限,还有一个变量path保存路过结点的值。将一个大树劈成两个左右子树(更新path),,,,,,一直给我劈,,,,,,直到只剩一个枝条没法劈,才将它与最短路径比较。
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<sstream>
using namespace std;
const int inf = 0x3f3f3f3f;
int inorder[10004], n, ans, minn;
int postorder[10004];
void build(int pl, int pr, int inl, int inr, int path)
{
if (pl > pr)
return;
if (pl == pr)
{
if (path + postorder[pl] <= minn)
{
if (path + postorder[pl] == minn)
{
ans = ans < postorder[pl] ? ans : postorder[pl];
}
else
{
minn = path + postorder[pl];
ans = postorder[pl];
}
}
return;
}
int fir = postorder[pr];
for (int i = inl; i <= inr; ++i)
{
if (inorder[i] == fir)
{
build(pl, pl + i - inl - 1, inl, i - 1, path + inorder[i]);
build(pr - (inr - i), pr - 1, i + 1, inr, path + inorder[i]);
break;
}
}
}
int main()
{
memset(inorder, 0, sizeof(inorder));
memset(postorder, 0, sizeof(postorder));
string s;
while (getline(cin, s))
{
if (s.size() == 0)
break;
stringstream st(s);
n = -1;
while (st >> inorder[++n])
;
getline(cin, s);
stringstream str(s);
int cn = 0;
ans = inf;
minn = inf;
while (str >> postorder[cn++])
;
build(0, n - 1, 0, n - 1, 0);
cout << ans << endl;
}
}原文:http://blog.csdn.net/qq_33665647/article/details/51331840