對於一顆給定的二叉樹,對任意兩個節點,求它們的最低的公共祖先。ios
下面就是這樣一道題,給定一棵樹的前序和中序遍歷(咱們知道這顆樹就是肯定的了),對於任兩個節點,求它們的最低公共主祖先。c++
PAT題目:1151 LCA in a Binary Tree (30 分)測試
#include<iostream> #include<cstdio> #include<map> using namespace std; int* pre,*in; map<int,int> pos; void LCA(int preRoot,int inL,int inR,int u,int v){ if(inL>inR) return; //inRoot,u,v:根節點,u,v在中序遍歷的位置 int inRoot=pos[pre[preRoot]],uInIdx=pos[u],vInIdx=pos[v]; if(uInIdx<inRoot&&vInIdx<inRoot){//u,v在中序遍歷中的位置小於根 LCA(preRoot+1,inL,inRoot-1,u,v); }else if((uInIdx<inRoot&&vInIdx>inRoot) ||(uInIdx>inRoot&&vInIdx<inRoot)){ printf("LCA of %d and %d is %d.\n",u,v,in[inRoot]); }else if(uInIdx>inRoot&&vInIdx>inRoot){ LCA(preRoot+1+(inRoot-inL),inRoot+1,inR,u,v); }else{ if(uInIdx==inRoot){ printf("%d is an ancestor of %d.\n",u,v); }else if(vInIdx==inRoot){ printf("%d is an ancestor of %d.\n",v,u); } } } int main(){ int m,n; scanf("%d%d",&m,&n); in=new int[n+1]; pre=new int[n+1]; for(int i=1;i<=n;i++){ scanf("%d",&in[i]); pos[in[i]]=i; } for(int i=1;i<=n;i++){ scanf("%d",&pre[i]); } while(m--){ int a,b; scanf("%d%d",&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){ printf("ERROR: %d is not found.\n",a); }else if(pos[b]==0){ printf("ERROR: %d is not found.\n",b); }else{ LCA(1,1,n,a,b); } } return 0; }
上面是對於一顆普通的二叉樹,若是這顆二叉樹又是一個二叉搜索樹,那麼還有以下的方法可用,並且是更好的方式,用上面的方法就會超時。spa
題目:1143 Lowest Common Ancestor (30 分)code
#include <iostream> #include <algorithm> #include <unordered_set> #define MAXSIZE 10001 using namespace std; struct Node{ int val; Node *lchild, *rchild; Node(int v){ val = v; lchild = rchild = NULL; } }; int pre[MAXSIZE] = {0}, in[MAXSIZE] = {0}; Node * inPreCreateTree(int inL, int inR, int preL, int preR){ if( preL > preR ){ return NULL; } int val = pre[preL]; Node * root = new Node(val); int mid; for( mid = inL; mid <= inR; mid++ ){ if( in[mid] == val ){ break; } } int numLeft = mid - inL; root->lchild = inPreCreateTree(inL, mid-1, preL+1, preL+numLeft); root->rchild = inPreCreateTree(mid+1, inR, preL+numLeft+1, preR); return root; } void LCA(Node * root, int lVal, int rVal, bool positionChanged){ if( root != NULL ){ if( root->val > lVal && root->val < rVal ){ if( positionChanged == false ){ cout<<"LCA of "<<lVal<<" and "<<rVal<<" is "<<root->val<<".\n"; }else{ cout<<"LCA of "<<rVal<<" and "<<lVal<<" is "<<root->val<<".\n"; } }else if( root->val == lVal ){ cout<<lVal<<" is an ancestor of "<<rVal<<".\n"; }else if( root->val == rVal ){ cout<<rVal<<" is an ancestor of "<<lVal<<".\n"; }else if( root->val > rVal ){ LCA(root->lchild, lVal, rVal, positionChanged); }else{ LCA(root->rchild, lVal, rVal, positionChanged); } } } int main(){ // ios::sync_with_stdio(false); // cin.tie(0); int m, n; cin>>m>>n; int val; unordered_set<int> s; for( int i = 0; i < n; i++ ){ cin>>val; in[i] = pre[i] = val; s.insert(val); } sort(in, in+n); Node * root = inPreCreateTree(0, n-1, 0, n-1); int u, v; for( int i = 0; i < m; i++ ){ cin>>u>>v; if( s.find(u) == s.end() && s.find(v) == s.end() ){ cout<<"ERROR: "<<u<<" and "<<v<<" are not found.\n"; }else if( s.find(u) == s.end() ){ cout<<"ERROR: "<<u<<" is not found.\n"; }else if( s.find(v) == s.end() ){ cout<<"ERROR: "<<v<<" is not found.\n"; }else{ bool positionChanged = false; if( u >= v ){ swap(u, v); positionChanged = true; } LCA(root, u, v, positionChanged); } } return 0; }
方法2:ci
該方法對於這題會有一個測試點超時get
#include<iostream> #include<algorithm> #include<map> using namespace std; const int maxn=10010; int pre[maxn],in[maxn]; map<int,int> pos; void LCA(int preRoot,int inL,int inR,int u,int v){ if(inL>inR) return; int uInIdx=pos[u],vInIdx=pos[v]; int inRoot=pos[pre[preRoot]]; if(uInIdx<inRoot&&vInIdx<inRoot){ LCA(preRoot+1,inL,inRoot-1,u,v); }else if(uInIdx<inRoot&&vInIdx>inRoot||(uInIdx>inRoot&&vInIdx<inRoot)){ printf("LCA of %d and %d is %d.\n",u,v,pre[preRoot]); }else if(uInIdx>inRoot&&vInIdx>inRoot){ LCA(preRoot+(inRoot-inL)+1,inRoot+1,inR,u,v); }else{ if(uInIdx=inRoot){ printf("%d is an ancestor of %d.\n",u,v); }else if(vInIdx==inRoot){ printf("%d is an ancestor of %d.\n",v,u); } } } int main(){ int m,n; cin>>m>>n; for(int i=1;i<=n;i++){ cin>>pre[i]; in[i]=pre[i]; } sort(in+1,in+n+1); for(int i=1;i<=n;i++){ pos[in[i]]=i; } while(m--){ 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){ printf("ERROR: %d is not found.\n",a); }else if(pos[b]==0){ printf("ERROR: %d is not found.\n",b); }else{ LCA(1,1,n,a,b); } } return 0; }