教材原题

假设我们有n个直径各不相同的螺钉以及n个相应的螺母。我们一次只能比较一对螺钉和螺母,来判断螺母是大于螺钉、小与螺钉还是正好适合螺钉。然而我们不能拿两个螺母做比较,也不能拿两个螺钉做比较

我们的问题是要找到每一对匹配的螺钉和螺母。为该问题设计一个算法,它的平均效率必须属于Θ(n log n)。

题意分析

可能看完题目,不知道它到底要我们干什么,又没有规定输入,也没有要求输出。这跟我们做oj的题很不一样,oj的题目只要在规定时间和空间内给出正确答案就行了。而这种算法分析设计题,输入、输出、算法和代码都要我们设计。

有的同学可能直接对 螺钉 和 螺母 两个数组分别进行快排,然后输出结果。很显然,分别快排,就违背了上面 标粗 的题意要求。

在正式设计算法和写代码之前,我们简单想想输入、输出。输入肯定就是螺母和螺钉两个数组,输出我们可以简单一点,直接输出两个排序后的数组,但是中间的算法是符合我们题意要求的。

还有一个问题!划分时,元素下标不断变化,而一开始我们也没有对各个螺钉和螺母进行编号。我们这样输入和输出,怎么体现 上面标粗的 “找到” 呢? 输出是两个有序数组,一一对应就可以体现我们 “找到” “匹配到”了。就好比现实中,我们可以不需要通过编号标识,而直接通过手动移动位置,让匹配螺钉和螺母放到一块。

说这么多,是因为:在真正写代码之前,进行一定的逻辑分析是有必要的。

算法分析

假设我们一开始随便选一枚螺钉A,假设就取区间最左侧那一枚(一开始区间是[0, n-1])。然后在螺母的对应区间([0, n-1])首先找到与螺钉A对应的螺母a。然后把螺母a与区间最左侧的螺母调换位置。然后根据螺钉A,在区间内,对螺母a进行划分。注意,这里是根据 螺钉A , 而不是根据调换了位置的螺母a!!!不然就违背题意了。螺母一次划分后。同理以 螺母a 来划分 螺钉,注意此时的区间还是 [0, n-1]。

上面是一次划分的算法。我们需要多次划分,每次划分都要缩小区间。详见代码。

快排的模板代码

先贴一下快排的模板代码,这个实现比教材的要更简单一点,虽然算法思路是一样的。

void quicksort(int x[],int left,int right)  //快速排序
{if(left<right){int i=left,j=right,key=x[left];while(i<j){while(i<j&&x[j]>=key)j--;if(i<j)x[i++]=x[j];while(i<j&&x[i]<=key)i++;if(i<j)x[j--]=x[i];}x[i]=key;quicksort(x,left,i-1);quicksort(x,i+1,right);}
}

解题代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;const int N = 9;void print(int ld[], int lm[]) {printf("ld:");for (int i = 0; i < N; i++) {printf("%d ", ld[i]);}printf("\n");printf("lm:");for (int i = 0; i < N; i++) {printf("%d ", lm[i]);}printf("\n");
}// 进行一次划分
// [l, r] { 5, 2, 4, 3, 1 }
int partition(int x[], int l, int r, int key) {// 假设key是螺钉,则首先在螺母中找到与之匹配的螺母// 然后与最左侧的螺母交换,使之称为中轴,方便之后作partition for(int i=l; i<=r; i++)if(x[i]==key){swap(x[i], x[l]);break;}// 以key划分螺母 int i=l,j=r;int t=x[l]; // 暂存中轴 while(i<j){while(i<j&&x[j]>=key) // 注意,这里要与key做比较,不要用t来比较 j--;if(i<j)x[i++]=x[j];while(i<j&&x[i]<=key)i++;if(i<j)x[j--]=x[i];}x[i]=t;//    printf("i=%d\n", i);
//    for(int i = l; i <= r; i++ ) {
//      printf("%d ", x[i]);
//  }return i;
} // [l, r]
void match(int ld[], int lm[], int l, int r) {if (l < r) {// 随便选一个 ld,此处以区间的最左侧(第1个)那个 ld 为例子 int ldKey = ld[l];// 返回划分之后 lm 的位置 // 此时与选的ld对应的lm,(划分之后)在下标为 pos 的位置int pos1 = partition(lm, l, r, ldKey);// 选这个 lm,来划分 ld int lmKey = lm[pos1]; int pos2 = partition(ld, l, r, lmKey); // 在这里pos1与pos2相等的 print(ld, lm);printf("pos1=%d pos2=%d\n", pos1, pos2);match(ld, lm, l, pos1-1); match(ld, lm, pos1+1, r); }
}int main() {// 为了方便模拟,螺钉和螺母都以数字1-9编号// 而且,约定编号越大,直径越大int ld[N] = { 5, 9, 3, 7, 1, 8, 2, 4, 6 };int lm[N] = { 7, 1, 4, 2, 5, 6, 9, 8, 3 };match(ld, lm, 0, N-1);return 0;
}

“注意,这里要与key做比较,不要用t来比较 ”

可能有人不太理解注释这句话。因为螺钉和螺母都是用相同的数字来表示,可能感觉不到差别。

假如你以 小写字母 来 表示螺钉,以大写字母 来 表示螺母。那么上面代码中比较的地方就需要改动,那样可能会更能理解上面这句注释和原题的题意要求!

【螺钉和螺母问题】【算法分析与设计】假设我们有n个直径各不相同的螺钉以及n个相应的螺母...相关推荐

  1. 用c语言验证装载问题 回溯法,《算法分析与设计》期末考试复习题纲(完整版)...

    <算法分析与设计>期末复习题 一.选择题 1. 算法必须具备输入.输出和( D )等4个特性. A.可行性和安全 性 B .确定性和易读性 C.有穷性和安全 性 D .有穷性和确定性 2. ...

  2. 算法分析与设计实验报告——二分搜索算法的实现

    算法分析与设计实验报告--二分搜索算法的实现 目录: 算法分析与设计实验报告--二分搜索算法的实现 一. 实验目的 二.实验要求 三. 实验原理 四. 实验过程(步骤) 五. 运行结果 六.实验分析与 ...

  3. 中北大学算法分析与设计实验报告一(BF算法)

    中北大学算法分析与设计实验报告一(BF算法) 1.实验名称 实验一 算法基础实验:数理基础与串匹配程序设计 2.实验目的 以字符串匹配问题为例,结合C等编程语言和链表.堆.栈等数据结构知识,基于BF算 ...

  4. 算法入门章——引出贯穿《算法导论》全书的算法分析和设计框架

    刚刚认真学习了第二章,习题还未做.现在趁热打铁,先来凭空总结和回忆一下整个过程. 本章主要线索:通过引入两个算法,从插入排序分析和设计排序算法,引出了整本书后续各章节的算法设计和分析的框架.这个框架归 ...

  5. NJUPT算法分析与设计期末考试202.12.1

    NJUPT算法分析与设计期末考试2021.11.24 判断 简答 1.算法是什么?算法的时间复杂度是什么?衡量的原则,标准,工具 2.分支限界法扩展活节点的方式有哪两种,有什么差别? 3.回溯法搜索子 ...

  6. 算法分析与设计——贪心法实验报告

       算法导论  课程设计 成 绩 题    目:    贪心法 学院班级:        1613013         学    号:      16130130216       姓    名: ...

  7. 算法分析与设计——回溯法实验报告

       算法导论  课程设计 成 绩 题    目:    回 溯 法 学院班级:        1613013         学    号:      16130130216       姓     ...

  8. 一周搞定期末考系列之《算法分析与设计》

    转眼就到了期末复习算法的时候了 真的是一点都不慌啊 算法分析与设计这门课,由于是一门选修课,而且我对算法分析没有过多的热爱,所以没有对这门课程进行全方位的深度的学习与复习,但是我相信,将下列算法的全部 ...

  9. 程振波 算法设计与分析_算法分析与设计之动态规划

    动态规划同样是一种将问题分解为求解子问题的方法,不过与分治不同的是,动态规划算法的子问题不是相互独立的,而是有公共的部分,即有重叠子问题,这个时候使用分治算法,将会重复计算公共的子问题,效率很低!而用 ...

  10. 一本好的教辅,可以少走很多弯路:算法分析和设计 王晓东

    算法分析和设计 王晓东 我觉得第三版JAVA版本最好,第4版是C++版本,删减了几章. 可以配合北大屈婉玲教授的视频课程一起看 自己走了一些弯路,希望后续的可以避免以下 下载地址如下,也可以淘宝买本二 ...

最新文章

  1. 【任务脚本】0530更新淘宝618活动领喵币脚本,OrangeJs基于autojs全自动程序稳定运行,向大神致敬...
  2. 探索 Linux 内存模型--转
  3. mfc 消息消息队列概念_必看入门秘籍——解密原理:消息中间件之RabbitMQ
  4. Py之pyecharts:python包之数据可视化包pyecharts简介、安装、使用方法之详细攻略
  5. Mining Precision Interface From Query Logs -- 学习笔记(三)
  6. 使用AWS Lambda在Go中构建RESTful API
  7. hdp安装 不安装mysql_hdp安装及使用问题汇总(一)
  8. IndexError: list index out of range image_name=self.images_name[index]
  9. React中的Portal组件
  10. Godaddy 上的域名服务器状态查询
  11. 一、RabbitMQ安装
  12. 如何通过“限制管理权限”来保护您的企业?
  13. html5拼音显示,HTML5:给汉字加拼音?收起展开组件?
  14. 循环闹钟c语言,闹钟设置四天一个循环,自定义周期循环提醒便签
  15. 广东诚美计算机专修学院 概况,广州各大高校
  16. 原生js监听滚动条_原生JS实现滚动条监听
  17. 安卓备份文件提取 .bak文件解包 abe.jar
  18. STM32控制舵机转动_从0到1
  19. TCP FIN_WAIT2由来
  20. win下搭建小程序服务器,win下搭建小程序服务器

热门文章

  1. 5.9拉普拉斯矩阵的谱分解,谱图卷积,图卷积演变过程
  2. Linux-用户操作
  3. linux开机禁用vga设备,用vga_switcheroo在Linux下(开启KMS)彻底关闭某一可切换显卡的简单教程...
  4. Linux驱动开发(十三)---USB驱动HID开发学习(鼠标)
  5. ddm模型公式_绝对估值法DDM、DCF模型和RNAV简介
  6. 阿里开源数据同步工具--DataX
  7. 建筑智能化资质升级需要的企业工程业绩
  8. Tensorflow2.0---SSD网络原理及代码解析(一)
  9. 程序员自学编程的6种方法,高效学习
  10. 2022年自然语言处理行业研究报告