题目原文:

Nuts and bolts. A disorganized carpenter has a mixed pile of n nuts and n bolts. The goal is to find the corresponding pairs of nuts and bolts. Each nut fits exactly one bolt and each bolt fits exactly one nut. By fitting a nut and a bolt together, the carpenter can see which one is bigger (but the carpenter cannot compare two nuts or two bolts directly). Design an algorithm for the problem that uses nlogn compares (probabilistically).

分析:

题意是有一堆螺帽和螺钉,分别为n个,每个螺帽只可能和一个螺钉配对,目标是找出配对的螺帽和螺钉。螺帽和螺钉的是否配对只能通过螺帽和螺钉比较,不能通过两个螺帽或两个螺钉的比较来判断。比较次数要求限制在nlogn次

设计过程中思考了如下几个问题:

1. 螺帽和螺钉的配对怎么判断?

  -螺帽和螺钉分别设计成不同的对象,每个对象都有个size属性,通过判断不同对象的size是否相等来判断是否配对

2. 为什么不能通过把螺帽和螺钉分别排序,然后对应位置一一配对的方式进行设计?

  -假如那堆螺帽和螺钉中分别有落单的不能配对的,这种排序后靠位置来匹配的配对方式就明显不合适了,也就是说这种做法鲁棒性太差

3. 既然不能分别排序,那采用把螺帽和螺钉混在一起排序的方式如何?

  -恩,貌似可行,但遇到螺帽和螺钉中分别有落单的不能配对的情况,我怎么判断某个位置i处元素是与i-1处的元素配对?还是与i+1处的元素配对?还是i处元素落单呢?

综上几个问题考虑之后,决定如下设计:

a. 现将螺帽进行快速排序,复杂度nlogn

b. 逐个遍历螺钉组中的每个螺钉,在已排序的螺帽中,采用二分查找的方法查找其配对的螺帽。比较次数nlogn,满足题目要求

代码如下

 package week3;
/**
* 螺帽和螺钉共有父类
* @author evasean www.cnblogs.com/evasean/
*/
public class NBParent {
public NBParent(int size){
this.size = size;
}
private int size;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
 package week3;
/**
* 螺帽类
* @author evasean www.cnblogs.com/evasean/
*/
public class Nut extends NBParent{
public Nut(int size){
super(size);
}
}
 package week3;
/**
* 螺钉类
* @author evasean www.cnblogs.com/evasean/
*/
public class Bolt extends NBParent{
public Bolt(int size){
super(size);
}
}
 package week3;

 import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import edu.princeton.cs.algs4.StdRandom;
/**
* 螺帽类
* @author evasean www.cnblogs.com/evasean/
*/
public class NutsAndBolts {
Map<Nut, Bolt> pairs = new HashMap<Nut, Bolt>(); // 存储配对的螺帽和螺丝对
Nut[] nuts;
Bolt[] bolts;
int n; public NutsAndBolts(Nut[] nuts, Bolt[] bolts, int n) {
this.nuts = nuts;
this.bolts = bolts;
this.n = n;
} private int compare(NBParent v, NBParent w) {
int vsize = v.getSize();
int wsize = w.getSize();
if (vsize == wsize) return 0;
else if (vsize > wsize) return 1;
else return -1;
}
private void exch(NBParent[] nb, int i, int j){
NBParent t = nb[i];
nb[i]=nb[j];
nb[j]=t;
} public Map<Nut, Bolt> findPairs() {
sort(bolts,0,n-1); //先对bolts进行快速排序
for(int i = 0; i<n;i++){ //遍历nuts,并在bolts中寻找其成对的bolt
Nut nut = nuts[i];
Bolt bolt= findBolt(nut);
if(bolt != null)
pairs.put(nut, bolt);
}
return pairs;
}
private Bolt findBolt(Nut nut){ //在排好序的bolts中二分查找nut
int lo = 0;
int hi = n-1;
while(lo<=hi){
int mid = lo+(hi-lo)/2;
int cr = compare(bolts[mid],nut);
if(cr<0) lo = mid+1;
else if(cr>0) hi = mid-1;
else return bolts[mid];
}
return null;
}
private void sort(NBParent[] nb, int lo, int hi){
if(hi<=lo) return;
int j = partition(nb,lo,hi);
sort(nb,lo,j-1);
sort(nb,j+1,hi);
} private int partition(NBParent[] nb, int lo, int hi){
int i = lo;
int j = hi+1;
NBParent v = nb[lo];
while(true){
while(compare(nb[++i],v)<0) if(i==hi) break;
while(compare(nb[--j],v)>0) if(j==lo) break;
if(i>=j) break;
exch(nb,i,j);
}
exch(nb,lo,j);
return j;
} public static void main(String[] args) {
int n = 10;
Nut[] nuts = new Nut[n];
Bolt[] bolts = new Bolt[n];
for (int i = 0; i < n-1; i++) {
Nut nut = new Nut(i + 1);
nuts[i] = nut;
Bolt bolt = new Bolt(i + 2);
bolts[i] = bolt;
}
//故意做一对不一样的
nuts[n-1] = new Nut(13);//nuts的size分别为{1,2,3,4,5,6,7,8,9,13}
bolts[n-1] = new Bolt(1);//bolts的size分别是{2,3,4,5,6,7,8,9,10,1}
StdRandom.shuffle(nuts);
StdRandom.shuffle(bolts);
NutsAndBolts nb = new NutsAndBolts(nuts, bolts, n);
Map<Nut, Bolt> pairs = nb.findPairs();
Iterator<Entry<Nut, Bolt>> iter = pairs.entrySet().iterator();
while(iter.hasNext()){
Entry<Nut, Bolt> e = iter.next();
Nut nut = e.getKey();
Bolt bolt = e.getValue();
System.out.print("<"+nut.getSize()+","+bolt.getSize()+">,");
}
System.out.println();
}
}

Coursera Algorithms week3 快速排序 练习测验: Nuts and bolts的更多相关文章

  1. Coursera Algorithms week3 快速排序 练习测验: Decimal dominants(寻找出现次数大于n/10的元素)

    题目原文: Decimal dominants. Given an array with n keys, design an algorithm to find all values that occ ...

  2. Coursera Algorithms week3 快速排序 练习测验: Selection in two sorted arrays(从两个有序数组中寻找第K大元素)

    题目原文 Selection in two sorted arrays. Given two sorted arrays a[] and b[], of sizes n1 and n2, respec ...

  3. Coursera Algorithms week3 归并排序 练习测验: Shuffling a linked list

    题目原文: Shuffling a linked list. Given a singly-linked list containing n items, rearrange the items un ...

  4. Coursera Algorithms week3 归并排序 练习测验: Counting inversions

    题目原文: An inversion in an array a[] is a pair of entries a[i] and a[j] such that i<j but a[i]>a ...

  5. Coursera Algorithms week3 归并排序 练习测验: Merging with smaller auxiliary array

    题目原文: Suppose that the subarray a[0] to a[n-1] is sorted and the subarray a[n] to a[2*n-1] is sorted ...

  6. Coursera Algorithms week1 算法分析 练习测验: Egg drop 扔鸡蛋问题

    题目原文: Suppose that you have an n-story building (with floors 1 through n) and plenty of eggs. An egg ...

  7. Coursera Algorithms week1 算法分析 练习测验: 3Sum in quadratic time

    题目要求: Design an algorithm for the 3-SUM problem that takes time proportional to n2 in the worst case ...

  8. (转)Nuts and Bolts of Applying Deep Learning

    Kevin Zakka's Blog About Nuts and Bolts of Applying Deep Learning Sep 26, 2016 This weekend was very ...

  9. Coursera Algorithms week2 基础排序 练习测验: Dutch national flag 荷兰国旗问题算法

    第二周课程的Elementray Sorts部分练习测验Interview Questions的第3题荷兰国旗问题很有意思.题目的原文描述如下: Dutch national flag. Given ...

随机推荐

  1. Java_Web三大框架之Hibernate+jsp+selvect+HQL查询数据

    俗话说:"好记性不如烂笔头".本人学习Hibernate也有一个星期了,对Hibernate也有一个初步的了解.下面对Hibernate显示数据做个笔记,使用租房系统的Hibern ...

  2. hibernate注解之@Onetomany、@Manytoone、@JoinColumn

    @Onetomany用于实体类与数据库表映射中少的一方,请看下面的例子. 假设一个用户只有一种角色,用户和角色是onetomany的关系 用户实体 @Entity @Table(name=" ...

  3. mstsc windows7/10远程桌面身份验证错误 要求的函数不受支持

    之前好好的能远程桌面连接到服务器,但是今天来就不能连接上了,并提示:身份验证错误.要求的函数不受支持. 猜想可能是Windows又更新了什么鬼,后面查询资料知道是由于CredSSP加密Oracle修正 ...

  4. javascript中 (function(){})();如何理解?

    javascript中 (function(){})();如何理解? javascript中: (function(){})()是匿名函数,主要利用函数内的变量作用域,避免产生全局变量,影响整体页面环 ...

  5. 1040 有几个PAT (25 分)

    题目链接:1040 有几个PAT (25 分) 做这道题目,遇到了新的困难.解决之后有了新的收获,甚是欣喜! 刚开始我用三个vector数组存储P A T三个字符出现的位置,然后三层for循环,根据字 ...

  6. JAVA学习总结-常用数据结构

    java中集合框架其实就是数据结构的实现的封装; 参考资料:任小龙教学视频 1,什么是数据结构? 数据结构是计算机存储,组织数据的方式; 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合; ...

  7. Linux之iptables(三、命令--->单主机)

    iptables命令规则格式: iptables [-t table] SUBCOMMAND chain [-m matchname[per-match-options]] -j targetname ...

  8. tp5 微信支付开发流程

    1.用户在选择商品后,向APi提交包含它所选择商品的相关信息. 2.APi在接收到信息后,需要检查订单相关商品的库存量. 3.有库存,把订单数据存入数据库中= 下单成功了,返回客户端消息,告诉客户端可 ...

  9. mac上常用的命令

    平时会经常遇到的问题做一个总结

  10. noip模拟赛 正方形

    题目描述在一个10000*10000的二维平面上,有n颗糖果.LYK喜欢吃糖果!并且它给自己立了规定,一定要吃其中的至少C颗糖果!事与愿违,LYK只被允许圈出一个正方形,它只能吃在正方形里面的糖果.并 ...