• PAT.1143 Lowest Common Ancestor


    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    题解

    测试点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);
    
    • 1
    • 2
    • 3
    • 4

    改成:

    	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);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    特判一下就完事儿了。

  • 相关阅读:
    「前端+鸿蒙」核心技术HTML5+CSS3(十)
    内网渗透技巧
    智汇华云|基于TPM2.0的windows11虚拟机实践
    提取字母后数字
    线上展厅设计步骤
    计算机毕业设计选什么题目好?springboot 职业技术学院图书管理系统
    1347. 制造字母异位词的最小步骤数 (中等,Counter)
    group by用法
    Go的优雅终止姿势
    定时任务系列(8)-Quartz启动核心原理之集群
  • 原文地址:https://blog.csdn.net/weixin_43662405/article/details/126894031