加载中...

前序和后序遍历

https://www.acwing.com/problem/content/1611/

思路:
由于n只有30,直接暴力枚举,虽说理论上限很高可能会超时,但是其实dfs过程中剪枝了许多。
关键在如何dfs,由于知道前序和后序,无法确定每次左右子树的长度,所以每次枚举左子树的长度,又因为总长一定,现在左右子树长度都知道了,又因为题目中说了,只要其中一种方案即可,这个题目的方案满足乘法原理,只要方案大于1,直接break即可。
注意:
1.l1>r1的时候return 1,因为此时为空树,而空树也算做一种合法方案。
2.当pre[l1]!=post[r2]的时候直接return 0,因为此时肯定不是合法的。

#include <iostream>

using namespace std;

const int N = 40;

int n;
int pre[N], post[N];

int dfs(int l1, int r1, int l2, int r2, string& in)
{
    if (l1 > r1) return 1;
    if (pre[l1] != post[r2]) return 0;

    int cnt = 0;
    for (int i = l1; i <= r1; i ++ )  // 枚举左子树包含的节点数量
    {
        string lin, rin;
        int lcnt = dfs(l1 + 1, i, l2, l2 + i - l1 - 1, lin);
        int rcnt = dfs(i + 1, r1, l2 + i - l1 - 1 + 1, r2 - 1, rin);

        if (lcnt && rcnt)
        {
            in = lin + to_string(pre[l1]) + ' ' + rin;
            cnt += lcnt * rcnt;
            if (cnt > 1) break;
        }
    }

    return cnt;
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++ ) cin >> pre[i];
    for (int i = 0; i < n; i ++ ) cin >> post[i];

    string in;    
    int cnt = dfs(0, n - 1, 0, n - 1, in);

    if (cnt > 1) puts("No");
    else puts("Yes");

    in.pop_back();
    cout << in << endl;

    return 0;
}
posted @ 2022-08-19 19:39  英雄不问出处c  阅读(37)  评论(0编辑  收藏  举报