CODE[VS]1029 遍历问题

题目:http://codevs.cn/problem/1029/
思路:如果前序位置i处与后序L-i处的字符相等,则该点可能为左根也有可能为右根,而不同则表示此处为左,右分界处。分治求解。
题解:

/* 1029 遍历问题 */
#include <stdio.h>

#define MAXN 28

char preorder[MAXN], postorder[MAXN];       /* 前序,后序字符串 */
int length;                                 /* 字符长度 */

/* 计算中序遍历的可能情况 */
int get_inorder(int x1, int y1, int x2, int y2)
{
    int ans = 1;
    int i;
    int lx, ly, rx, ry;
    char lr, rr;        /* 左根值,右根值 */
    if(x1 >= y1 || x2 >= y2)
    {
        return 1;
    }
    /* 测试 - 打印前序,后序遍历字符串 */
    /*
    for(i = x1; i <= y1; i++)
    {
        printf("%c", preorder[i]);
    }
    printf(" <> ");
    for(i = x2; i <= y2; i++)
    {
        printf("%c", postorder[i]);
    }
    printf("\n");
    */
    /***********************************/
    /* 如果前后字符相同,则有两种可能 */
    for(i = 1; x1 + i <= y1; i++)
    {
        /* 如果前序,后序字符相等,则有两种可能*/
        if(preorder[x1 + i] != postorder[y2 - i])
        {
            break;
        }
        ans = ans * 2;
    }

    /* 记录根节点位置 */
    lx = x1 + i;
    ry = y2 - i;
    lr = preorder[lx];  /* 左子树根字符 */
    rr = postorder[ry]; /* 右子树根字符 */
    /* 计算前序遍历中右根字符位置 */
    ly = y1;
    for(i = lx; i <= y1; i++)
    {
        if(preorder[i] == rr)
        {
            ly = i;
            break;
        }
    }
    /* 计算后序遍历中左根字符位置 */
    rx = x2;
    for(i = ry; i >= x2; i--)
    {
        if(postorder[i] == lr)
        {
            rx = i;
            break;
        }
    }
    ans = ans * get_inorder(lx, ly - 1, x2, rx) * get_inorder(ly, y1, rx + 1, ry);
    return ans;
}

/* 主函数入口 */
int main()
{
    int ans;
    /* 打开数据文件 */
    FILE *fp;
    if(NULL == (fp = fopen("data.txt", "r")))
    {
        return 1;
    }
    /***************/
    /* 读取前序,后序遍历字符串 */
    fscanf(fp, "%s", preorder);
    fscanf(fp, "%s", postorder);

    /* 计算字符串长度 */
    length = 0;
    while('\0' != preorder[++length]);
    ans = get_inorder(0, length - 1, 0, length - 1);
    printf("%d", ans);
    /* 关闭数据文件 */
    fclose(fp);
    /****************/
    return 0;
}

思路:前序为根(r)->左(la)->右(rb),后序为左(la)->右(rb)->根(r),如果前序为根(r)->X,后序为根(r)->X,则X可能为左(la),也可能为右(rb),即出现一个分支可能。计算所有字符串中分叉数量ans,则中序遍历有2^ans个可能。

题解:

/* 1029 遍历问题 */
#include <stdio.h>

#define MAXN 28

char preorder[MAXN], postorder[MAXN];       /* 前序,后序字符串 */
int length;                                 /* 字符长度 */
/* 主函数入口 */
int main()
{
    int ans;
    int i, j;

    /* 读取前序,后序遍历字符串 */
    scanf("%s", preorder);
    scanf("%s", postorder);

    /* 计算字符串长度 */
    length = 0;
    while('\0' != preorder[++length]);
    ans = 0;
    for(i = 1; i < length; i++)
    {
        for(j = 0; j < length; j++)
        {
            if(preorder[i] == postorder[j] && preorder[i - 1] == postorder[j + 1])
            {
                ans++;
            }
        }
    }    
    printf("%d", 1<<ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/QQ604666459/article/details/78323696
今日推荐