簡介:
《算法設計手冊》(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上沒有詳細的擴展情況的介紹。)