《算法設計手冊》面試題解答 第二章

簡介:

  《算法設計手冊》(The Algorithm Design Manual)課後面試題和解答。包括:未知大小的集合選取k個元素、數據備份方案、尋找數組最小數時賦值語句執行次數的期望、100層大樓拋大理石(拋燈泡)、電子秤找不足量金幣、天平找重球、公司合併方案總數、海盜分贓等。

 

2-43.

  從n元集合中取一個k元子集,並要求每個元素概率相等。若n未知又該如何解決?

解答:

  原問題在http://www.cnblogs.com/wuyuegb2312/p/3141292.html#title3已經解答清楚了。

  此文也解決了從未知行數中等概率選擇一行的方法,那麼如果需要選擇k個呢?爲了簡化起見,限定未知的n>=k。那麼先選擇前k個元素;對第k+1個元素,以概率k/(k+1)選擇之,並以等概率1/k代替已選擇的k個元素中的一個。

  這樣,這一輪裏前k個元素中某一個能留下的概率爲1/(k+1) + [k/(k+1)] * [(k-1)/k] = k/(k+1)。那麼對於第k+2個元素,類似地,以概率k/(k+2)選擇之,並以等概率1/k代替已選擇的k個元素中的一個,循環直至所有元素遍歷結束。

  (解答啓發自http://blog.csdn.net/fall221/article/details/8805733

 

2-44.

  有1000份各不相同的數據項和1000個存儲數據的結點,每個結點可以存放3份不同的數據項。制定一個備份方案,使其在某些結點失效時損失最小。當任意3個結點失效時,丟失的數據的期望數值是多少?

解答:

  讓所有結點存儲內容不完全相同,是基本的。如果令結點n保存數據項n、n+1、n+2(取1000的模),最好情況是3個結點失效時不損失數據(各不連續或者2個連續),最壞情況是3個連續結點失效(n、n+1、n+2),損失n+2這一份數據。這個概率很容易計算,是1/10^(-6)。

  相關延伸閱讀:

  RAID思想,保存異或結果,不過我算的概率相同:http://stackoverflow.com/questions/10291690/1000-items-1000-nodes-3-items-per-node-best-replication-scheme-to-minimize-da

  類似的處理:http://blog.csdn.net/quietsound/article/details/9285375

 

2-45.

  從n+1個數中找出最小數時,min = A[i]語句執行次數的期望。其中數組下標A[0...n]。

  (首次賦值min=A[0]計算在內)

解答:

  首先想到的是逆序對。但是通過序列[1,3,2]和[1,2,3]可知,兩者賦值次數是一樣的,顯然與逆序對無關。

  直接從期望入手,記E(n)爲n+1個數時的該賦值語句期望執行次數。

  最小的數在末尾A[n]的概率爲1/n,這時需要一次賦值。

  最小的數不在末尾A[n],則末尾處不需賦值,增加的賦值數爲0。

  這樣,有E(n) = E(n-1) +1/n且E(0)=0。其中E(n-1)已經包括最小的數在非A[n]處的所有情況。因此E(n)爲

          

  n比較大時,約爲lnn。

  (解答來自於:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.45

 

2-46.

  你有一棟100層高的大廈和2塊大理石。你想找出一個最低樓層,從這個樓層開始,在它和比它更高的樓層上拋下大理石,落地會碎。如果有無限多塊大理石,怎麼最快找出這一層(拋的最少次數)?如果只有兩塊呢?(另一種說法:100層樓扔燈泡)

解答:

  無限多塊時,很容易想到用折半查找來進行。但是如果使用最少的大理石塊又該如何找呢?注意到如果某次拋下時大理石未碎,那麼下次仍能夠使用。爲了只用兩塊大理石來判斷樓層數,由於碎裂的最低樓層是一定的,先做分析:

  假設n是最多需要的測試次數(確定但未知,最壞情況),在第n層扔,如果碎了,由於只剩下一個燈泡,爲了確定1至n-1層中哪一層,最壞情況是從1層一直扔到n-1層,共n-1次,加上之前的1次是n次,不超過n;如果未碎,那麼上到2n-1層再扔,碎時同樣有最壞情況從n+1層扔到2n-2層共n-2次,加上之前的是n次。依次類推,總結出每次測試都是n次,且確定的樓層範圍是:n->2n-1->3n-2->...,即n + (n-1) + ... +1>100。求解使不等式成立的最小正整數是n=14。

  (解答來自於:http://stackoverflow.com/questions/6547/two-marbles

 

2-47.

  有10袋金幣,其中9袋中每個金幣都是10克,另1袋中每個金幣都是9克。給你一個能夠數字顯示重量的電子秤,找出全是9克的金幣的那一袋。

解答:

  看到稱重量可能會聯想到用天平找幾堆商品中不足量的一份。可是這裏用的是能顯示具體數值的電子秤哎!如果還用天平的思想,可太死板了。

  想想權重的概念,解法馬上有了:從1號至10號袋中分別取1至10個金幣,放到電子秤上。如果10袋全是10克的,那麼應該顯示550克;而缺幾克,那就說明那個袋子裏是9克的金幣。一次解決,是不是很簡單?

  當然,權重也可以用別的方案分配,不過上面是最簡單的。

  (參考自:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.47

 

2-48.

  8個外表一樣的球,其中7個等重,另1個比它們重。用天平在2次的比較後找出這個重球。

解答:

  由於有“2次比較”的提示,這個就簡單了:把球分爲(1,2,3),(4,5,6),(7,8)三組,第一次稱(1,2,3)和(4,5,6),若一組重,那麼將3箇中取2個可得重的是這2個之一還是其餘一個;否則將(7,8)稱重。

  如果按這個思路,9個球也能夠解決。

 

2-49.

  將n個公司合併成1個公司,一共有幾種不同的方式合併?

解答:

  記合併方式f(n)種,f(n)=f(n-1)*g(n),其中g(n)是將n個公司通過一次合併變爲n-1個公司的方法。顯然g(n)爲組合數C(n,2)。遞推公式解得

  

  (參考自http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.49

 

2-50.

  Rramanujan數是可以寫作a^3+b^3=c^3+d^3的數,其中a!=c且b!=d,或者a!=d且b!=c。找出滿足所有給定小於n的Rramanujan數。

解答:

  編程實現如下

#include<stdio.h>
int main() {
    int n, i, count=0, j, k, int_count;
    printf("Enter the number of values needed: ");
    scanf("%d", &n);
    i = 1;
    while(count < n) {
       int_count = 0;
       for (j=1; j<=((int(pow(i, 1.0/3)); j++) {
          for(k=j+1; k<=((int(pow(i,1.0/3)); k++) {
              if(j*j*j+k*k*k == i)
              int_count++;
          }
       }
       if(int_count == 2) {
          count++;
          printf("\nGot %d Hardy-Ramanujan numbers %d", count, i);  
       }
       i++;
    }
}

  注意幾點以加速搜索:

  確保j<k,這樣另一對j、k與原來的必然互不相等;

  兩個for循環終止條件是j^3<i。

  (參考自:http://stackoverflow.com/questions/11410798/finding-hardy-ramanujan-numbers

 

2-51.

  6個海盜分300美刀,分贓方法如下:有由資歷最深的提出分配方案,進行投票。如果獲得半數及以上支持,那麼按照他的分配方案進行;否則,其他海盜殺掉他,資歷第二深的海盜來提出分配方案,其後仍要投票表決,依次類推。請分析分配方法。(所有海盜都以自己存活爲最優考慮,保證存活的條件下才儘可能希望多獲得美刀。)

解答:

  將海盜按資歷有深到淺編號爲1,2,3,4,5,6。假設只剩下5,6兩個海盜時,5無論提出怎樣的分配方案,都能使支持過半(自己的一票),那麼分配方法必然是:

  (5,6) ---->(300,0)

  時間倒流,加入海盜4。海盜4爲了防止投票不過半而被殺死,需要拉攏海盜6。由於6在上一種情況裏什麼也分不到,這時只要4分給6,無論多少,6都會同意。這樣,4給他最少的數目,即1。而5希望進入下一輪投票,因此只有給他全部300刀才能拉攏。由於投票已過半(2/3),不必拉攏5。此時分配方案爲:

  (4,5,6) ---->(299,0,1)

  加入海盜3時,出於類似的考慮,提出這樣的方案:

  (3,4,5,6) ---->(299,0,1,0),這樣能拉攏5,不至於3死後,5什麼也分不到。

  (299,1,0,0)必然不能拉攏4,因爲將3幹掉後4能獲得299。至於爲什麼不用(299,0,0,1)這樣的方案呢?此時6無論是否同意,他都有機會在本輪獲得1美刀或者把3幹掉後的下一輪必然獲得1美刀。因此3的倖存與否是未知的,他不能做出這種使自己生命可能受到威脅的分配方式。後面的分析類似。有:

  (2,3,4,5,6) --->(298,0,1,0,1)

  (1,2,3,4,5,6) ----> (298,0,1,0,1,0)

  (參考自:http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_2.51,這裏我補充了不少分析。)

 

2.52.

  如果2.51中只有1美刀來分贓,誰會得到它,在這個分配過程中會死多少人?

解答:

  和上一題分析類似,當只有2個海盜時,年長那個一定能得到那1美刀;當海盜數大於等於3時,任何分配給自己的分配方案都不能保證自己一定能存活,不如直接分給倒數第二個海盜。(但即使如此,也可能被殺死。投票將演化成殺死一部分海盜,然後讓倒數第二個海盜獲得的過程。)

  (更一般的情況請參考http://en.wikipedia.org/wiki/Pirate_game。注意,中文wiki上沒有詳細的擴展情況的介紹。)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章