PAT 1143 Lowest Common Ancestor (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.
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.

考點

  樹,BST特性

思路

  這個題目和1151 LCA in a Binary Tree很類似。具體的解決思路就是。如果u和v在點a的左右子樹上,那麼a一定就是u和v的LCA。按照1151的做法,BST的中序遍歷是有序的,因此可以根據前序序列得到中序序列。這樣,就可以遞歸的去找LCA。具體解法如代碼一。這樣做會運行超時,我想也是必然的,畢竟沒有領會到BST的真正有意。於是有了參照柳神的代碼二。
我們知道如果u和v在點a的左右子樹上,那麼a一定就是u和v的LCA。由於樹是BST,如果uv分別爲a的左右子樹的話,就必然有uv一個比a大,一個比a小,問題就輕鬆解決了,甚至比代碼一還要簡潔。

代碼

代碼一,解法類似於1151題,能拿到26分

#include <bits/stdc++.h>
using namespace std;
int m,n;
map<int, int> pos;//記錄數字的位置 
vector<int> in, pre;//中序和前序序列 
void lca(int inleft,int inright,int root,int a,int b){
    if(inleft>inright) return;
    int rpos = pos[pre[root]],apos=pos[a],bpos=pos[b];//確定根和ab在中序序列中的位置
    if(apos<rpos&&bpos<rpos){//ab均在左子樹上 
        lca(inleft,rpos-1,root+1,a,b); 
    }else if(apos<rpos&&bpos>rpos || apos>rpos&&bpos<rpos){//ab在根的兩側 
        printf("LCA of %d and %d is %d.\n", a, b, in[rpos]);
    }else if(apos>rpos&&bpos>rpos){
        lca(rpos+1,inright,root+(rpos-inleft)+1,a,b);
    }else if(apos==rpos){
        printf("%d is an ancestor of %d.\n", a, b);
    }else if(bpos==rpos){
        printf("%d is an ancestor of %d.\n", b, a);
    }
} 
int main(){
    cin>>m>>n;
    pre.resize(n+1,0);
    in.resize(n+1,0);
    for(int i=1;i<=n;i++){
        cin>>pre[i];
        in[i]=pre[i];
    } 
    sort(in.begin(),in.end());
    for(int i=1;i<in.size();i++){
        pos[in[i]] = i; 
    }
    for(int i=0;i<m;i++){
        int a,b;
        cin>>a>>b;
        if (pos[a] == 0 && pos[b] == 0)//均不在 
            printf("ERROR: %d and %d are not found.\n", a, b);
        else if (pos[a] == 0 || pos[b] == 0)//有一個不在 
            printf("ERROR: %d is not found.\n", pos[a] == 0 ? a : b);
        else//均在 
            lca(1, n, 1, a, b);
    }
}

代碼二,參考柳神

#include <iostream>
#include <vector>
#include <map>
using namespace std;
map<int, bool> mp;
int main() {
    int m, n, u, v, a;
    scanf("%d %d", &m, &n);
    vector<int> pre(n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &pre[i]);
        mp[pre[i]] = true;
    }
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        for(int j = 0; j < n; j++) {
            a = pre[j];
            if ((a >= u && a <= v) || (a >= v && a <= u)) break;
        } 
        if (mp[u] == false && mp[v] == false)
            printf("ERROR: %d and %d are not found.\n", u, v);
        else if (mp[u] == false || mp[v] == false)
            printf("ERROR: %d is not found.\n", mp[u] == false ? u : v);
        else if (a == u || a == v)
            printf("%d is an ancestor of %d.\n", a, a == u ? v : u);
        else
            printf("LCA of %d and %d is %d.\n", u, v, a);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章