PAT 甲级 1151 LCA in a Binary Tree (30 分)

The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants.

Given any two nodes in a binary tree, you are supposed to find their LCA.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers: M (≤ 1,000), the number of pairs of nodes to be tested; and N (≤ 10,000), the number of keys in the binary tree, respectively. In each of the following two lines, N distinct integers are given as the inorder and preorder traversal sequences of the binary tree, respectively. It is guaranteed that the binary tree can be uniquely determined by the input sequences. Then M lines follow, each contains a pair of integer keys U and V. All the keys are in the range of int.

Output Specification:

For each given pair of U and V, print in a line LCA of U and V is A. if the LCA is found and A is the key. But if A is one of U and V, print X is an ancestor of Y. where X is A and Y is the other node. If U or V is not found in the binary tree, print in a line ERROR: U is not found. or ERROR: V is not found. or ERROR: U and V are not found…

Sample Input:

6 8
7 2 3 4 6 5 1 8
5 3 7 2 6 4 8 1
2 6
8 1
7 9
12 -3
0 8
99 99

Sample Output:

LCA of 2 and 6 is 3.
8 is an ancestor of 1.
ERROR: 9 is not found.
ERROR: 12 and -3 are not found.
ERROR: 0 is not found.
ERROR: 99 and 99 are not found.

算法分析
1、题目给出中序遍历和前序遍历,前序遍历的第一个是根结点,然后找到中序遍历中这个数的位置,左边的是左子树,右边的是右子树。
2、首先判断需要寻找的两个数是否存在于给定的这棵树中,使用两个visit,一个存储负数,一个存储非负数,直接映射检车是否存储。
3、分成两大类,
(1)两个数都在这棵树上;
(2)至少存在一个数不在这棵树上,这种情况好处理,基本上就是直接输出了。
下面对于上面第一种情况分析。

判断当前两个数在当前树的位置,如何判断呢?我们已知了,当前树的大小,通过前序遍历,第一个结点时根结点,然后在中序遍历中找到它的位置,设置为root_pos,此处使用的是位置,每一个数在中序遍历中的位置,然后就可以直接比较啦。A_pos, B_pos,具体见LCA函数代码,就是对这些情况的分类处理。

#include <iostream>
#include <cstdio>
#include <unordered_map>
using namespace std;
int M,N;
int a[10005];
int b[10005];
bool visit_1[0xffffff]={false};
bool visit_2[0xffffff]={false};
unordered_map<int,int> pos;
bool contain(int a)
{
    if(a>=0)
        return visit_1[a];
    else
        return visit_2[-a];
}
void LCA(int l1,int r1,int l2,int r2,int A,int B)
{
    int root_pos = pos[ b[l2] ]; // 首先找出根结点在中序遍历中的位置
    if( pos[A] < root_pos && pos[B] < root_pos ) //都在左边
        LCA(l1,root_pos-1,l2+1,l2+root_pos-l1,A,B);
    else if( pos[A] > root_pos && pos[B] > root_pos ) //都在右边
        LCA(root_pos+1,r1,l2+root_pos-l1+1,r2,A,B);
    else if( pos[A] == root_pos ) //A是根
        printf("%d is an ancestor of %d.\n",A,B);
    else if( pos[B] == root_pos ) //B是根
        printf("%d is an ancestor of %d.\n",B,A);
    else if( pos[A] > root_pos && pos[B] < root_pos ||  
            pos[A] < root_pos && pos[B] > root_pos ) //一个在左,一个在右
        printf("LCA of %d and %d is %d.\n",A,B,b[l2]);
}
int main()
{
    cin>>M>>N;
    for(int i=1;i<=N;i++) //inorder
    {
        scanf("%d",&a[i]);
        pos[a[i]]=i;
    }
    for(int i=1;i<=N;i++) //preorder
    {
        scanf("%d",&b[i]);
        if(b[i]>=0)
            visit_1[b[i]]=true;
        else
            visit_2[-b[i]]=true;
    }
    int A,B;
    while(M--)
    {
        scanf("%d %d",&A,&B);
        bool flag1=contain(A);
        bool flag2=contain(B);
        if(flag1&&flag2)
            LCA(1,N,1,N,A,B);
        else{
            if(!flag1&&!flag2)
                printf("ERROR: %d and %d are not found.\n",A,B);
            else if(!flag1)
                printf("ERROR: %d is not found.\n",A);
            else
                printf("ERROR: %d is not found.\n",B);
        }
    }
    return 0;
}
发布了174 篇原创文章 · 获赞 18 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41173604/article/details/100564577