1143. Lowest Common Ancestor (30) 思维 + O(n)建立BST树

传送门


思路:

    果然是个很水的题,当时把自己考崩了,预感到凉了结果就真的凉了...当时也是zz,为啥老想着建树呢》????首先要判断是否出现过,肯定是map一下了.


其次就是找LCA,(考场傻逼到手刚LCA),因为这是一个BST树所以存在一个很重要的性质就是 左<根<右.

    那么对于给定的两个值我们从根节点开始,往下走,总会走到一个节点分叉,那么这个点就是他们的最近公共祖先了.

那么最多1w个点,我们每次直接for一下就好了啊,找到 一个节点值 >  u1 ,< u2的即可.

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e4+5;
int n,m;
map<int,int>mp;
int a[maxn];
int main()
{
	while(~scanf("%d %d",&m,&n))
	{
		mp.clear();
		for(int i = 1;i <= n;++i)
		{
			scanf("%d",&a[i]);
			mp[a[i]] = 1;
		}
		for(int i = 1;i <= m;++i)
		{
			int u,v;
			scanf("%d %d",&u,&v);
			if(mp[u] == 0 && mp[v] == 0)
			printf("ERROR: %d and %d are not found.\n",u,v);
			else if(mp[u] == 0 || mp[v] == 0)
			printf("ERROR: %d is not found.\n",mp[u] == 0?u : v); 
			else
			{
				int f ;
				for(int j = 1;j <= n;++j)
				{
					f = a[j];
					if((f > v && f < u) || (f > u && f < v) || f == u || f == v) 
						break;
				} 
				if(f == u || f == v)
				printf("%d is an ancestor of %d.\n",f,u == f ? v : u);
				else
				printf("LCA of %d and %d is %d.\n",u,v,f);
			}
		}
	}
	return 0;
}


当然这个题建树也是可以做,先建树在跑LCA.由于1w个点,所以每次输入一个Insert,当是一条链就T了(-.-我就是这样T到死的)

这里来学一个新的建树方法,递归O(n)建立BST树.考虑到给定的为一个先序遍历,那么肯定是“根左右”,也就是第一个一定是根节点,那么怎么找到哪些是左子树哪些是右子树中的节点呢?还是利用BST的性质,左面都比根节点小右面都比根节点大,所以我们只需把当前区间的序列和根节点比较,直到找到一个大于他的就是左右子树间的分界线了,然后一直递归下去.

#include<bits/stdc++.h>

using namespace std;
const int maxn = 1e4+5;
int a[maxn];
int n,m;
map<int,int>mp;
struct node
{
    int val;
    node *l;
    node *r;
    node()
    {
        l = r = nullptr;
    }
};
node* build(int l,int r)
{
    if(l > r) return nullptr;
    if(l == r)
    {
        node *tmp = new node;
        tmp -> val = a[l];
        //cout << '-' << ' ' << tmp -> val << endl;
        return tmp;
    }
    int i = l + 1;
    while(i <= r && a[i] < a[l]) ++i;
    node *tmp = new node;
    tmp -> val = a[l];
   //cout << '*' << ' ' << tmp -> val << endl;
    tmp -> l = build(l + 1,i - 1);
    tmp -> r = build(i,r);
    return tmp;
}
int _find(node *root,int u,int v)
{
    if(root == nullptr) return -1;
    //cout << root -> val << endl;
    if(root -> val == u || root -> val == v)
        return root -> val;
    if(root -> val > u && root -> val < v)
        return root -> val;
    if(root ->  val > v)
    return _find(root -> l,u,v);
    if(root -> val < u)
    return _find(root -> r,u,v);
}
int main()
{
    while(~scanf("%d %d",&m,&n))
    {
        mp.clear();
        for(int i = 1;i <= n;++i)
        {
           scanf("%d",&a[i]);
           mp[a[i]] = 1;
        }
        node *root;
        root = build(1,n);
      //  cout << root -> val<<endl;
        for(int i = 1;i <= m;++i)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            if(mp[u] == 0 && mp[v] == 0)
                printf("ERROR: %d and %d are not found.\n",u,v);
            else if(mp[u] == 0 || mp[v] == 0)
                printf("ERROR: %d is not found.\n",mp[u] == 0 ? u : v);
            else
            {
                int x1 = u,x2 = v;
                if(x1 > x2) swap(x1,x2);
               int f = _find(root,x1,x2);
               if(f == u || f == v)
                    printf("%d is an ancestor of %d.\n",f,f == u ? v : u);
                else
                    printf("LCA of %d and %d is %d.\n",u,v,f);
            }

        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章