A1143. Lowest Common Ancestor

Posted zhuqiwei-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了A1143. Lowest Common Ancestor相关的知识,希望对你有一定的参考价值。

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.

A binary search tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node‘s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node‘s key.
  • Both the left and right subtrees must also be binary search trees.

Given any two nodes in a BST, 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 BST, respectively. In the second line, N distinct integers are given as the preorder traversal sequence of the BST. 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 BST, 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
6 3 1 2 5 4 8 7
2 5
8 7
1 9
12 -3
0 8
99 99

Sample Output:

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


技术分享图片
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<map>
using namespace std;
typedef struct NODE{
    struct NODE* lchild, *rchild;
    int data;
}node;
int M, N;
int pre[10010], in[10010];
map<int, int>mp;
node* create(int preL, int preR, int inL, int inR){
    if(preL > preR)
        return NULL;
    node* root = new node;
    root->data = pre[preL];
    int mid;
    for(int i = inL; i <= inR; i++){
        if(in[i] == root->data){
            mid = i;
            break;
        }
    }
    int len = mid - inL;
    root->lchild = create(preL + 1, preL + len, inL, mid - 1);
    root->rchild = create(preL + len + 1, preR, mid + 1, inR);
    return root;
}
node* find(node* root, int u, int v){
    if(root == NULL || root->data == u || root->data == v)
        return root;
    node* ll = find(root->lchild, u, v);
    node* rr = find(root->rchild, u, v);
    if(ll != NULL && rr != NULL){
        return root;
    }
    if(ll != NULL){
        return ll;
    }
    if(rr != NULL){
        return rr;
    }
}
int main(){
    scanf("%d%d", &M, &N);
    for(int i = 0; i < N; i++){
        scanf("%d", &in[i]);
        pre[i] = in[i];
        mp[pre[i]] = 1;
    }
    sort(in, in + N);
    node* root = create(0, N - 1, 0, N - 1);
    for(int i = 0; i < M; i++){
        int u, v;
        scanf("%d%d", &u, &v);
        if(mp.count(u) == 0 && mp.count(v) == 0){
            printf("ERROR: %d and %d are not found.
", u, v);
        }else if(mp.count(u) == 0){
            printf("ERROR: %d is not found.
",u );
        }else if(mp.count(v) == 0){
            printf("ERROR: %d is not found.
",v);
        }else{
            node* ans = find(root, u, v);
            if(ans->data != u && ans->data != v){
                printf("LCA of %d and %d is %d.
", u, v, ans->data);
            }else if(ans->data == u){
                printf("%d is an ancestor of %d.
", u, v);
            }else{
                printf("%d is an ancestor of %d.
", v, u);
            }
        }
    }
    cin >> N;
    return 0;
}
View Code

总结:

1、题意:给出一个BST的先序序列,再给出两个点u、v,要求在BST中找出uv的最低公共祖先。

2、BST已知先序建树有两种方法,1)先序序列的顺序就是插入顺序,直接依次插入。2)对先序进行排序得到中序序列(BST的中序是从小到大的有序序列),由先序和中序进行递归建树。由于本题的N个数很大,使用insert方法会超时,尤其是在树高度为N时,复杂度为O(n^2)。所以最好采用先序+中序建树。

3、找最低的公共祖先。这种类型的任务一般采用后序递归遍历的办法:先处理左子树,再处理右子树,等左右子树都完成后,综合左右子树返回的信息与root的信息进行某些处理,再返回本层递归的结果。具体到本题,uv只有两种情况:1)即uv分别在某w节点的左右子树,则w为所求。2)uv本身就有祖先后代关系,则若u为祖先,u即为所求。

    后序递归,若root为NULL或uv时,说明查找失败或成功,直接返回root。否则说明root为普通节点,先对root的左右子树分别查找。若左右子树都不空时,说明uv分别在root的左右两侧子树,则root即为所求。否则,说明uv在root的一侧子树,若在root的左侧,则将root左侧的查找结果返回。




以上是关于A1143. Lowest Common Ancestor的主要内容,如果未能解决你的问题,请参考以下文章

1143 Lowest Common Ancestor

1143. Lowest Common Ancestor (30)

PAT 1143 Lowest Common Ancestor

1143 Lowest Common Ancestor (30分)

PAT 甲级 1143 Lowest Common Ancestor

PAT 1143 Lowest Common Ancestor[难][BST性质]