PAT A1151 LCA in a Binary Tree【树的遍历】

这道题虽然是让我们求最近公共祖先,但是并不需要用什么倍增之类的复杂算法解决,而是采用递归遍历的方式即可。解决这道题之前,我也没什么思路,先看了看柳神的博客,一下子恍然大悟,这道题其实并不难。
这道题的思路是,根据先序遍历和中序遍历给出的数组,递归建树,在建树的过程中,如果两个点一个点位于当前树根的左边,另一个位于右边,则当前树根就是要求的LCA。注意,这里的“左边”“右边”指的是在中序遍历序列中的左右,因为中序遍历是以左子树-根-右子树的方式遍历的。如果两个点均位于左边,那么LCA肯定在当前根节点的左子树,如果均位于右边,那么LCA就在右子树。
这道题虽然思路不难,但是编写代码的时候,我也遇到了一些问题,记录如下:

  • 这道题给定的全部节点都在int的范围内,但是不超过10000个,所以可以利用map,把这些节点全映射到1到10000这几个数字之中。
  • 在我判断如下条件:当一个点位于树根左边,一个点位于树根右边,则当前树根就是要求的LCA的时候,只判断了一种情况,即x左y右,但是忘记了判断y左x右的情况。
  • 最后我一直有一个节点超时,分析后发现是我每次遍历的时候都要根据先序遍历中的第一个节点(根节点)求出该节点在中序遍历中的位置,时间复杂度大概为O(nmlogn),可以在最开始就求出所有节点在中序遍历中的位置,复杂度只有O(nm)。
  • 当我把LCA存到ans中的时候,我忘记了我所有的数都经过了一次映射,因此输出的是1-10000之间的数,而不是正确答案。由于题目中给的数据正好就是位于1-n之间,很难发现这个错误,因此,测试数据的时候可以把所有节点的值都设置为负数,再经过测试,自己的错误就一目了然了。
#include <iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstdlib>
#include<queue>
#include<cstring>
#include<set>
#include<list>
#include<unordered_set>
using namespace  std;
int m,n;
int pre[10010],in[10010];//pre:先序遍历,根-左-右  in:中序遍历 左-根-右
map<int,int>pos;
map<int,int>pos2;
int ans;
bool isXAnc=false,isYAnc=false;
int fatherPos[10010];
void search(int preL,int preR,int inL,int inR,int x,int y)
{
    if(preL>preR||inL>inR)
    {
       // cout<<"当前区间不存在"<<endl;
        return;
    }
    if(x<inL||x>inR||y<inL||y>inR)
    {
        //cout<<"x和y不在区间内"<<endl;
        return;
    }
    int newFather=pre[preL];
    int inFatherPos=fatherPos[newFather];
    /*
    for(int i=inL;i<=inR;i++)
        if(in[i]==newFather)
        {
            inFatherPos=i;
            break;
        }
        */
   // cout<<"inFatherPos:"<<inFatherPos<<endl;
   //     cout<<"newFather:"<<newFather<<endl;
    if((x<inFatherPos&&y>inFatherPos)||(y<inFatherPos&&x>inFatherPos))
    {

        ans=pos[newFather];
       // cout<<"答案是"<<ans<<endl;
        return;
    }
    else if(x==inFatherPos)
    {
        ans=pos[in[x]];
        isXAnc=true;
        return;
    }
    else if(y==inFatherPos)
    {
        ans=pos[in[y]];
        isYAnc=true;
        return;
    }
    int leftInL,leftInR,rightInL,rightInR;
    leftInL=inL;
    leftInR=inFatherPos-1;
    rightInL=inFatherPos+1;
    rightInR=inR;
    int leftChildNum,rightChildNum;
    leftChildNum=leftInR-leftInL+1;
    rightChildNum=rightInR-rightInL+1;
    if(leftChildNum>0)
    {
        if(x<inFatherPos&&y<inFatherPos)
            search(preL+1,preL+leftChildNum,leftInL,leftInR,x,y);
    }
    if(rightChildNum>0)
    {
        if(x>inFatherPos&&y>inFatherPos)
            search(preL+leftChildNum+1,preR,rightInL,rightInR,x,y);
    }

}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        pos.insert(pair<int,int>(i,x));
        pos2.insert(pair<int,int>(x,i));
        in[i]=i;
    }

    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        int id=pos2[x];
        pre[i]=id;
    }
    for(auto i=pos.begin();i!=pos.end();i++)
    {
        int curFather=i->first;
        for(int j=1;j<=n;j++)
            if(in[j]==curFather)
            {
                fatherPos[curFather]=j;
                break;
            }
    }

    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        int xid=pos2[x];
        int yid=pos2[y];
        if(xid==0&&yid==0)
        {
            printf("ERROR: %d and %d are not found.\n",x,y);
        }else if(xid==0)
        {
            printf("ERROR: %d is not found.\n",x);
        }
        else if(yid==0)
        {
            printf("ERROR: %d is not found.\n",y);
        }
        else{
            int inXPos,inYPos;
            isXAnc=false;
            isYAnc=false;
            for(int j=1;j<=n;j++)
            {
                if(in[j]==xid)
                {
                    inXPos=j;
                }
                if(in[j]==yid)
                {
                    inYPos=j;
                }
            }
          //  cout<<"inXPos:"<<inXPos<<" inYPos:"<<inYPos<<endl;
            search(1,n,1,n,inXPos,inYPos);
            if(isXAnc)
            {
                printf("%d is an ancestor of %d.\n",x,y);
            }
            else if(isYAnc)
            {
                printf("%d is an ancestor of %d.\n",y,x);
            }
            else printf("LCA of %d and %d is %d.\n",x,y,ans);
        }
    }
}
/*
6 8
-7 -2 -3 -4 -6 -5 -1 -8
-5 -3 -7 -2 -6 -4 -8 -1
 */
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值