分治螺钉与螺帽问题

假设我们有n个直径各不相同的螺钉以及n个相应的螺母。我们一次只能比较一对螺钉和螺母,来判断螺母是大于螺钉、小于螺钉还是正好适合螺钉。然而,我们不能拿两个螺母做比较,也不能拿两个螺钉做比较。我们的问题是要找到每一对匹配的螺钉和螺母。为该问题设计一个算法,它的平均效率必须属于集合O(nlogn)。

  1. 解法:类似于快速排序的思想,第一次选出一枚螺钉与所有螺帽比较,并将比此螺钉大的螺帽放到左侧,比此螺钉小的螺帽放到右侧,同时也选出了与之正好对应的螺帽。用与之正好对应的螺帽把螺钉分为比此螺帽大的,和比此螺帽小的。重复此过程则螺帽与螺钉实现一一对应。时间复杂度为O(n*logn),空间复杂度为O(n)。
#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cmath>


using namespace std;

   int n;


void match(int ld[],int lm[],int tm[],int l,int r)

{


    if(r>l)

{

    //---------用螺钉处理螺帽数组---------

int mid=ld[(l+r)/2];

int l1=l,r1=r;

for(int i=l;i<=r;++i)

{

     if(lm[i]<mid)   //小于当前螺钉的螺帽放在左侧。

     {

         tm[l1]=lm[i];

         ++l1;

     }

     if(lm[i]>mid)  //大于当前螺钉的螺帽放在右侧。

     {

         tm[r1]=lm[i];

         --r1;

     }

}

for(int i=l1;i<=r1;i++) tm[i]=mid; //把正好等于当前螺钉的螺帽放在中间

    for(int i=l;i<=r;++i)  //把分开后的数组赋值回螺帽数组

    {

  lm[i]=tm[i];

}


//-----------用螺帽处理螺钉数组----------

int mid1=mid;

int l2=l,r2=r;

for(int i=l;i<=r;++i)

{

     if(ld[i]<mid1)   //小于当前螺帽的螺钉放在左侧。

     {

         tm[l2]=ld[i];

         ++l2;

     }

     if(ld[i]>mid)  //大于当前螺帽的螺钉放在右侧。

     {

         tm[r1]=ld[i];

         --r2;

     }

}

for(int i=l2;i<=r2;i++) tm[i]=mid1; //把正好等于当前螺帽的螺钉放在中间

for(int i=l;i<=r;++i) //把分开后的数组赋值回螺钉数组

    {

  ld[i]=tm[i];

}  

match(ld,lm,tm,l,l1-1); //往左侧递归

match(ld,lm,tm,r1+1,r); //往右侧递归

   }

   else return;

}

int main()

{


   cin>>n;

   int *ld=new int[n+5];  //螺钉数组

   int *lm=new int[n+5];  //螺帽数组

   int *tem=new int[n+5]; //临时数组

   for(int i=0;i<n;i++) cin>>ld[i];

   for(int i=0;i<n;i++) cin>>lm[i];

   match(ld,lm,tem,0,n-1);

   cout<<"匹配后相当于两个数组排序"<<endl;

   cout<<"螺钉数组:";

   for(int i=0;i<n;++i) cout<<ld[i]<<" ";

   cout<<endl;

    cout<<"螺帽数组:";

   for(int i=0;i<n;++i) cout<<lm[i]<<" ";

   cout<<endl;

   delete [] ld;

   delete [] lm;

   delete [] tem;

   return 0;

}

 

  • 14
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值