pat 1151
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.
题意:给定一颗二叉树的前序和中序遍历序列,给出m对结点a,b,要求求出a,b的最深公共祖先结点
思路:不需要建树,对于一个结点c,假如在中序遍历序列中,考虑a,b,c在中序遍历中出现的位置,
如果a<c&&b>c或者a>c&&b<c,那么c一定是a,b的最深公共祖先
如果a<c&&b<c或者a>c&&b>c,那么a,b的最深公共祖先在c的左子树或者右子树中
如果a==c或者b==c,那么a,b的最深公共祖先是a或者b
按照这个思路递归即可,递归入口是根节点
注意点:记录某个结点在中序遍历中的位置的时候要用map而不能用普通数组hash表示,因为结点的值可能是负数,这样会发生数组越界错误。
代码如下:
#include<cstdio> #include<map> using namespace std; int pre[10100]; int in[10100]; map<int,int> all; void lca(int inl,int inr,int preRoot,int a,int b){ if(inl>inr) return; int inRoot=all[pre[preRoot]]; int ina=all[a]; int inb=all[b]; if(ina<inRoot&&inb<inRoot) lca(inl,inRoot-1,preRoot+1,a,b); else if((ina<inRoot&&inb>inRoot)||(ina>inRoot&&inb<inRoot)) printf("LCA of %d and %d is %d.\n",a,b,pre[preRoot]); else if(ina>inRoot&&inb>inRoot) lca(inRoot+1,inr,preRoot+1+inRoot-inl,a,b); else if(ina==inRoot){ printf("%d is an ancestor of %d.\n",a,b); } else if(inb==inRoot) printf("%d is an ancestor of %d.\n",b,a); } int main(){ int m,n; scanf("%d%d",&m,&n); for(int i=1;i<=n;i++){ scanf("%d",in+i); all[in[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",pre+i); } int a,b; for(int i=0;i<m;i++){ scanf("%d%d",&a,&b); if(all[a]==0&&all[b]==0) printf("ERROR: %d and %d are not found.\n",a,b); else if(all[a]==0||all[b]==0) printf("ERROR: %d is not found.\n",all[a]==0?a:b); else lca(1,n,1,a,b); } return 0; }