PAT.1143 Lowest Common Ancestor

PAT.1143 Lowest Common Ancestor,第1张

PAT.1143 Lowest Common Ancestor

题目链接

给定一棵BST的前序遍历,根据若干查询给出两节点的最低公共祖先(Lowest Common Ancestor)。

还是一贯的套路,根据前序中序建树,然后从根开始同时搜索两个节点,找到分叉点即可。

一些尝试

按照上面的思路,建树->判断->搜索,最终测试点2答案错误,关于测试点2的问题下面会讲。

以下代码得分29/30。

#include

using namespace std;
typedef long long ll;

struct node{
    int val;
    node *left,*right;
    node(){}
    node(int t){
        this->val = t;
        this->left = this->right = nullptr;
    }
};

int queryCnt,nodeCnt,preOrder[10005],inOrder[10005],tNode1,tNode2;
map<int,int> mark;
node *root;

node *build(int pl,int pr,int il,int ir){
    int rootVal = preOrder[pl],rootInOrderIndex = il;
    node *cNode = new node(rootVal);
    if(pl > pr || il > ir) return nullptr;
    else if(pl == pr || il == ir) return cNode;
    
    while(inOrder[rootInOrderIndex] != rootVal) rootInOrderIndex++;
    int leftChildSize = rootInOrderIndex - il;
    cNode->left = build(pl + 1,pl + leftChildSize,il,rootInOrderIndex - 1);
    cNode->right = build(pl + leftChildSize + 1,pr,rootInOrderIndex + 1,ir);
    
    return cNode;
}

int findLCA(int a,int b){
    int biggerNode = max(a,b),smallerNode = min(a,b);
    node *ptr = root,*lcaPtr = nullptr;
    bool isBiggerAnc = false,isSmallerAnc = false;
    while(ptr != nullptr){
        lcaPtr = ptr;
        if(biggerNode == ptr->val && smallerNode < ptr->val){
            //the bigger one is an ancestor of the smaller one
            isBiggerAnc = true;
            break;
        }else if(smallerNode == ptr->val && biggerNode > ptr->val){
            //the smaller one is an ancestor of the bigger one
            isSmallerAnc = true;
            break;
        }else{
            //LCA,落在两边的情况直接得到LCA,指向一边的情况继续搜索
            if(biggerNode < ptr->val){
                //向左
                ptr = ptr->left;
            }else if(smallerNode > ptr->val){
                //向右
                ptr = ptr->right;
            }else{
                //两边
                break;
            }
        }
    }
    if(isBiggerAnc) printf("%d is an ancestor of %d.\n",biggerNode,smallerNode);
    else if(isSmallerAnc) printf("%d is an ancestor of %d.\n",smallerNode,biggerNode);
    else printf("LCA of %d and %d is %d.\n",a,b,ptr->val);
}

//LCA肯定是两节点在搜索路径上的最低公共节点,从头到尾贪心找到最后一个连续的公共节点即可
int main(){
    cin>>queryCnt>>nodeCnt;
    for(int i = 0 ; i < nodeCnt ; ++i){
        cin>>preOrder[i];
        inOrder[i] = preOrder[i];
        mark[inOrder[i]]++;
    }
    sort(inOrder,inOrder + nodeCnt);
    root = build(0,nodeCnt - 1,0,nodeCnt - 1);
    while(queryCnt--){
        cin>>tNode1>>tNode2;
        if(mark[tNode1] == 0 && mark[tNode2] == 0) printf("ERROR: %d and %d are not found.\n",tNode1,tNode2);
        else if(mark[tNode1] == 0) printf("ERROR: %d is not found.\n",tNode1);
        else if(mark[tNode2] == 0) printf("ERROR: %d is not found.\n",tNode2);
        else findLCA(tNode1,tNode2);
    }
}
题解

测试点2其实就是查询的两个节点相同,而且都在树中的情况。

根据题干里说的,如果LCA是两个节点之一,就要输出a is an ancestor of b.这句话,而不是按照LCA的输出。那显然测试点2的情况下LCA的确是两个节点之一。

因此把:

	if(mark[tNode1] == 0 && mark[tNode2] == 0) printf("ERROR: %d and %d are not found.\n",tNode1,tNode2);
	else if(mark[tNode1] == 0) printf("ERROR: %d is not found.\n",tNode1);
	else if(mark[tNode2] == 0) printf("ERROR: %d is not found.\n",tNode2);
	else findLCA(tNode1,tNode2);

改成:

	if(mark[tNode1] == 0 && mark[tNode2] == 0) printf("ERROR: %d and %d are not found.\n",tNode1,tNode2);
	else if(mark[tNode1] == 0) printf("ERROR: %d is not found.\n",tNode1);
	else if(mark[tNode2] == 0) printf("ERROR: %d is not found.\n",tNode2);
	else if(tNode1 == tNode2) printf("%d is an ancestor of %d.\n",tNode1,tNode2);
	else findLCA(tNode1,tNode2);

特判一下就完事儿了。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/2991779.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-09-23
下一篇 2022-09-23

发表评论

登录后才能评论

评论列表(0条)

保存