《算法》第二章——Nuts and bolts(螺丝和螺帽)

来源:互联网 发布:网络赚钱论坛 编辑:程序博客网 时间:2024/05/17 08:50

题目:

Nuts and bolts. (G. J. E. Rawlins). You have a mixed pile of N nuts and N bolts and need to quickly find the corresponding pairs of nuts and bolts. Each nut matches exactly one bolt, and each bolt matches exactly one nut. By fitting a nut and bolt together, you can see which is bigger. But it is not possible to directly compare two nuts or two bolts. Given an efficient method for solving the problem.

Hint: customize quicksort to the problem. Side note: only a very complicated deterministic O(N log N) algorithm is known for this problem.


思路:

标准的快排啊, 用螺母把螺丝分区,每次分区得到三个结果,
A1,完全匹配的一对
A2,比螺母小的螺丝
A3,比螺母大的螺丝
将1中的螺丝取出,用它对螺母分区,可以得到
B1. 比螺丝小的螺母
B2. 比螺丝大的螺母
A2跟B1一一对应,A3跟B2一一对应,对(A2,B1)和(A3,B2)分别执行上述的算法,直至完全匹配。

代码:

/*假设螺钉和螺帽大小没有一样的。    每次取nuts数组中最后一个元素到bolts数组中去找和它配对的元素,这样可以避免nuts数组中后部元素前移。*/#include<iostream>using namespace std;int partition(int *nuts,int *bolts,int lo,int hi){//为了保证操作nuts和bolts数组的一致性,将每次配对成功的元素放在hi的位置。  int nuts_t = nuts[hi];  int i=lo;  int j=hi;  int bolt_match=0;  while(true)  {//在bolts中找到配的nuts并将bolts分区    while(bolts[i] <= nuts_t)    {      if(nuts_t == bolts[i])      {//先判断匹配的情况——找到完全相同的一对        bolt_match = bolts[i];        cout<<nuts_t<<"&"<<bolts[i]<<endl;        for(int k = i + 1;k <= hi;k++)        {//把当前匹配的元素位置通过后面的元素前移一格的方式填充          bolts[k -1] = bolts[k];        }        j--;//j一定指向后面要移动的某个元素,所以需要跟着递减1        hi--;//数组长度减1//        for(int k=lo;k<=hi;k++)//          cout<<bolts[k]<<" ";//        cout<<endl;       // i++;这里不需要指针后移        if(i > hi)//别越界          break;      }      else      {        i++;        if(i > hi)//别越界          break;      }    }//从左往右找到第一个大的螺钉    while(bolts[j] >= nuts_t)    {      if(nuts_t == bolts[j])      {//先判断匹配的情况        bolt_match = bolts[j];        cout<<nuts_t<<"&"<<bolts[j]<<endl;        for(int k = j + 1;k <= hi;k++)        {//把当前匹配的元素位置通过后面的元素前移一格的方式填充          bolts[k -1] = bolts[k];        }        hi--;        j--;//j指针前移//        for(int k=lo;k<=hi;k++)//          cout<<bolts[k]<<" ";//        cout<<endl;        if(j < lo)//别越界          break;      }      else      {        j--;        if(j < lo)//别越界          break;      }    }//从右往左找到第一个小的螺钉    if(i >= j)//数组扫描过一遍    {      if(i == j)        cout<<"error"<<endl;      break;    }    int tmp = bolts[i];//交换    bolts[i] = bolts[j];    bolts[j] = tmp;  }//  for(int k=lo;k<=hi;k++)//    cout<<bolts[k]<<" ";//  cout<<endl;  i = lo;  j = hi;  while(true)  {//用上面bolts数组中找到的配对的螺钉,将nuts分区    while(nuts[i] < bolt_match)    {      i++;      if(i > hi)//别越界        break;    }    while(nuts[j] > bolt_match)    {      j--;      if(j < lo)//别越界        break;    }    if(i > j)      break;    int tmp = nuts[i];//交换    nuts[i] = nuts[j];    nuts[j] = tmp;  }//  for(int k=lo;k<=hi;k++)//    cout<<nuts[k]<<" ";//  cout<<endl;  return i;//第一个比较大的元素}void sort(int *nuts,int *bolts,int lo,int hi){  if(lo == hi)  {    cout<<nuts[hi]<<"&"<<bolts[hi]<<endl;    return;  }  else if(lo > hi)  {    return;  }  int j = partition(nuts,bolts,lo,hi);  hi--;//经过一次划分后会成功配对一次,相应的hi要减一//  cout<<"j->"<<j<<endl;//  cout<<"lo->"<<lo<<endl;//  cout<<"hi->"<<hi<<endl;  sort(nuts,bolts,lo,j-1);  sort(nuts,bolts,j,hi);}int main(){  int nuts[10] = {1,3,2,4,6,5,7,9,8,0};  int bolts[10] = {7,4,1,8,5,2,9,6,3,0};  sort(nuts,bolts,0,9);}


0 0
原创粉丝点击