1. 程式人生 > >Coursera Algorithms week3 快速排序 練習測驗: Nuts and bolts

Coursera Algorithms week3 快速排序 練習測驗: Nuts and bolts

big rand [] .com .cn ash oal stat 決定

題目原文:

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,滿足題目要求

代碼如下

 1 package week3;
 2 /**
 3  * 螺帽和螺釘共有父類
 4  * @author evasean www.cnblogs.com/evasean/
5 */ 6 public class NBParent { 7 public NBParent(int size){ 8 this.size = size; 9 } 10 private int size; 11 public int getSize() { 12 return size; 13 } 14 public void setSize(int size) { 15 this.size = size; 16 } 17 }
 1 package week3;
 2 /**
 3  * 螺帽類
 4  * @author evasean www.cnblogs.com/evasean/
 5  */
 6 public class Nut extends NBParent{
 7     public Nut(int size){
 8         super(size);
 9     }
10 }
 1 package week3;
 2 /**
 3  * 螺釘類
 4  * @author evasean www.cnblogs.com/evasean/
 5  */
 6 public class Bolt extends NBParent{
 7     public Bolt(int size){
 8         super(size);
 9     }
10 }
  1 package week3;
  2 
  3 import java.util.HashMap;
  4 import java.util.Iterator;
  5 import java.util.Map;
  6 import java.util.Map.Entry;
  7 import edu.princeton.cs.algs4.StdRandom;
  8 /**
  9  * 螺帽類
 10  * @author evasean www.cnblogs.com/evasean/
 11  */
 12 public class NutsAndBolts {
 13     Map<Nut, Bolt> pairs = new HashMap<Nut, Bolt>(); // 存儲配對的螺帽和螺絲對
 14     Nut[] nuts;
 15     Bolt[] bolts;
 16     int n;
 17 
 18     public NutsAndBolts(Nut[] nuts, Bolt[] bolts, int n) {
 19         this.nuts = nuts;
 20         this.bolts = bolts;
 21         this.n = n;
 22     }
 23 
 24     private int compare(NBParent v, NBParent w) {
 25         int vsize = v.getSize();
 26         int wsize = w.getSize();
 27         if (vsize == wsize) return 0;
 28         else if (vsize > wsize) return 1;
 29         else return -1;
 30     }
 31     private void exch(NBParent[] nb, int i, int j){
 32         NBParent t = nb[i];
 33         nb[i]=nb[j];
 34         nb[j]=t;
 35     }
 36     
 37     public Map<Nut, Bolt> findPairs() {
 38         sort(bolts,0,n-1); //先對bolts進行快速排序
 39         for(int i = 0; i<n;i++){ //遍歷nuts,並在bolts中尋找其成對的bolt
 40             Nut nut = nuts[i];
 41             Bolt bolt= findBolt(nut); 
 42             if(bolt != null)
 43                 pairs.put(nut, bolt);
 44         }
 45         return pairs;
 46     }
 47     private Bolt findBolt(Nut nut){ //在排好序的bolts中二分查找nut
 48         int lo = 0; 
 49         int hi = n-1;
 50         while(lo<=hi){
 51             int mid = lo+(hi-lo)/2;
 52             int cr = compare(bolts[mid],nut);
 53             if(cr<0) lo = mid+1;
 54             else if(cr>0) hi = mid-1;
 55             else return bolts[mid];
 56         }
 57         return null;
 58     }
 59     private void sort(NBParent[] nb, int lo, int hi){
 60         if(hi<=lo) return;
 61         int j = partition(nb,lo,hi);
 62         sort(nb,lo,j-1);
 63         sort(nb,j+1,hi);
 64     }
 65     
 66     private int partition(NBParent[] nb, int lo, int hi){
 67         int i = lo;
 68         int j = hi+1;
 69         NBParent v = nb[lo];
 70         while(true){
 71             while(compare(nb[++i],v)<0) if(i==hi) break;
 72             while(compare(nb[--j],v)>0) if(j==lo) break;
 73             if(i>=j) break;
 74             exch(nb,i,j);
 75         }
 76         exch(nb,lo,j);
 77         return j;
 78     }
 79 
 80     public static void main(String[] args) {
 81         int n = 10;
 82         Nut[] nuts = new Nut[n];
 83         Bolt[] bolts = new Bolt[n];
 84         for (int i = 0; i < n-1; i++) {
 85             Nut nut = new Nut(i + 1);
 86             nuts[i] = nut;
 87             Bolt bolt = new Bolt(i + 2);
 88             bolts[i] = bolt;
 89         }
 90         //故意做一對不一樣的
 91         nuts[n-1] = new Nut(13);//nuts的size分別為{1,2,3,4,5,6,7,8,9,13}
 92         bolts[n-1] = new Bolt(1);//bolts的size分別是{2,3,4,5,6,7,8,9,10,1}
 93         StdRandom.shuffle(nuts);
 94         StdRandom.shuffle(bolts);
 95         NutsAndBolts nb = new NutsAndBolts(nuts, bolts, n);
 96         Map<Nut, Bolt> pairs = nb.findPairs();
 97         Iterator<Entry<Nut, Bolt>> iter = pairs.entrySet().iterator();
 98         while(iter.hasNext()){
 99             Entry<Nut, Bolt> e = iter.next();
100             Nut nut = e.getKey();
101             Bolt bolt = e.getValue();
102             System.out.print("<"+nut.getSize()+","+bolt.getSize()+">,");
103         }
104         System.out.println();
105     }
106 }

Coursera Algorithms week3 快速排序 練習測驗: Nuts and bolts