PAT_A1143#Lowest Common Ancestor
Source:
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 andA
is the key. But ifA
is one of U and V, printX is an ancestor of Y.
whereX
isA
andY
is the other node. If U or V is not found in the BST, print in a lineERROR: U is not found.
orERROR: V is not found.
orERROR: 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:
- 二叉树的建立
- 二叉树的遍历
- 二叉查找树(Binary Search Tree)
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 }