PAT_A1143#Lowest Common Ancestor

Source:

PAT A1143 Lowest Common Ancestor (30 分)

Description:

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.

Keys:

Attention:

  • 该代码测试点4有时候会超时,可以看出来测试数据是不同的,考试的时候如果遇到一个测试点卡住了,不妨多提交几次,实在不行再优化
  • 技巧性方法:BST中u和v的公共祖先r一定是介于u和v之间的,根据这个思路,可以直接遍历先序序列求解
  • 更新了优化算法

Code:

  1 /*
  2 Data: 2019-06-25 14:50:00
  3 Problem: PAT_A1143#Lowest Common Ancestor
  4 AC: 54:02
  5 
  6 题目大意:
  7 BST定义:L < root <= R;
  8 给定BST中两个结点,找出其最近公共祖先
  9 输入:
 10 第一行给出,测试数M<=1e3,结点数N<=1e4
 11 第二行,先序给出N个不同的结点
 12 接下来M行,给出结点U和V
 13 
 14 基本思路:
 15 遍历结点U和V,并存储从root至U,V的路径
 16 比较路径上的结点,即可找到最近公共祖先
 17 */
 18 #include<cstdio>
 19 #include<vector>
 20 #include<map>
 21 using namespace std;
 22 const int M=1e4+10;
 23 map<int,int> mp;
 24 vector<int> p1,p2;
 25 int v1,v2,f1,f2,bst[M];
 26 struct node
 27 {
 28     int data;
 29     node *lchild, *rchild;
 30 };
 31 
 32 node *Create(int l, int r)
 33 {
 34     if(l > r)
 35         return NULL;
 36     node *root = new node;
 37     root->data = bst[l];
 38     int k;
 39     for(k=l+1; k<=r; k++)
 40         if(bst[k] > bst[l])
 41             break;
 42     root->lchild = Create(l+1,k-1);
 43     root->rchild = Create(k,r);
 44     return root;
 45 }
 46 
 47 void Search(node *root)
 48 {
 49     if(root == NULL)
 50         return;
 51     if(f1) p1.push_back(root->data);
 52     if(f2) p2.push_back(root->data);
 53     if(root->data==v1) f1=0;
 54     if(root->data==v2) f2=0;
 55     Search(root->lchild);
 56     Search(root->rchild);
 57     if(f1) p1.pop_back();
 58     if(f2) p2.pop_back();
 59 }
 60 
 61 int main()
 62 {
 63 #ifdef ONLINE_JUDGE
 64 #else
 65     freopen("Test.txt", "r", stdin);
 66 #endif // ONLINE_JUDGE
 67 
 68     int n,m;
 69     scanf("%d%d", &m,&n);
 70     for(int i=0; i<n; i++)
 71     {
 72         scanf("%d", &bst[i]);
 73         mp[bst[i]]=1;
 74     }
 75     node *root = Create(0,n-1);
 76     for(int i=0; i<m; i++)
 77     {
 78         scanf("%d%d", &v1,&v2);
 79         if(mp[v1]==0 && mp[v2]==0)
 80             printf("ERROR: %d and %d are not found.\n", v1,v2);
 81         else if(mp[v1]==0)
 82             printf("ERROR: %d is not found.\n", v1);
 83         else if(mp[v2]==0)
 84             printf("ERROR: %d is not found.\n", v2);
 85         else
 86         {
 87             p1.clear();f1=1;
 88             p2.clear();f2=1;
 89             Search(root);
 90             while(p1.size() < p2.size())
 91                 p2.pop_back();
 92             while(p1.size() > p2.size())
 93                 p1.pop_back();
 94             int pos=p1.size()-1;
 95             while(p1[pos] != p2[pos])
 96                 pos--;
 97             if(p1[pos] != v1 && p1[pos] != v2)
 98                 printf("LCA of %d and %d is %d.\n", v1,v2,p1[pos]);
 99             else if(p1[pos] == v1)
100                 printf("%d is an ancestor of %d.\n", v1,v2);
101             else
102                 printf("%d is an ancestor of %d.\n", v2,v1);
103         }
104     }
105 
106     return 0;
107 }

 优化算法

 1 #include<cstdio>
 2 #include<map>
 3 #include<algorithm>
 4 using namespace std;
 5 const int M=1e4+10;
 6 int pre[M],v1,v2;
 7 map<int,int> mp;
 8 
 9 void Travel(int root)
10 {
11     if((pre[root]<v1&&pre[root]>v2)||(pre[root]>v1&&pre[root]<v2))
12         printf("LCA of %d and %d is %d.\n", v1,v2,pre[root]);
13     else if(pre[root]==v1)
14         printf("%d is an ancestor of %d.\n",v1,v2);
15     else if(pre[root]==v2)
16         printf("%d is an ancestor of %d.\n",v2,v1);
17     else
18         Travel(root+1);
19 }
20 
21 int main()
22 {
23 #ifdef ONLINE_JUDGE
24 #else
25     freopen("Test.txt", "r", stdin);
26 #endif // ONLINE_JUDGE
27 
28     int n,m;
29     scanf("%d%d", &m,&n);
30     for(int i=1; i<=n; i++)
31     {
32         scanf("%d", &pre[i]);
33         mp[pre[i]]=1;
34     }
35     while(m--)
36     {
37         scanf("%d%d", &v1,&v2);
38         if(mp[v1]==0 && mp[v2]==0)
39             printf("ERROR: %d and %d are not found.\n",v1,v2);
40         else if(mp[v1]==0)
41             printf("ERROR: %d is not found.\n", v1);
42         else if(mp[v2]==0)
43             printf("ERROR: %d is not found.\n", v2);
44         else
45             Travel(1);
46     }
47 
48     return 0;
49 }

 

posted @ 2019-05-23 20:54  林東雨  阅读(295)  评论(0编辑  收藏  举报