ibm ponder this上個月的題目比較有趣:我在心裡面想乙個2到166之間的整數(包括2和166),你的任務是用盡可能少的是非問句(我只能回答是或者否)猜出這個數除1以外的最小約數是多少。
(1) 尋找一種策略使得在最壞情況下猜到答案的詢問次數最少。
(2) 尋找一種策略使得在平均情況下猜到答案的期望詢問次數最少。
第乙個問題很容易回答。雖然2到166之間的整數一共有165個,但它們的最小約數(以後我們說的「最小約數」都是指的不包括1的最小約數)只有38種。因此,事實上你只需要用二分法在38個可能的答案當中找出乙個就可以了。由於2^5=32,2^6=64,因此最壞情況下需要6次詢問才能保證猜到。
真正困難的是後面乙個問題:要想讓平均猜測次數盡可能少,我們該從**入手呢?
為了方便思考,不妨讓我們把這個問題簡化一下。假設題目條件中我心裡想的數字範圍是2到10之間的自然數,由於這些數的最小約數分別是2、3、2、5、2、7、2、3、2,只有四種情況,因此只需要兩個問題即可問出答案——比方說,第一次問「最小約數是2或3嗎」,回答「是」則再問「最小約數是2嗎」,回答「否」則問「最小約數是5嗎」,即可保證知道答案。若採用這種策略的話,不管我心裡想的是什麼數,你總是需要恰好兩次猜測才能猜出答案。但事實上,由於最小約數是2的可能性遠遠大於其它的數,因此減少最小約數是2時的猜測次數,增加最小約數是5和7時的猜測次數,雖然最壞情況下需要的猜測次數變多了,但我們或許能得到更優的平均猜測次數。我們可以這樣做:先問「最小約數是2嗎」。如果回答是,則直接猜到,因此當我心裡想的數是2、4、6、8、10中的乙個時,猜測次數僅為一次。如果回答否,則問題變為了下述子問題:當我心裡所想的數為3、5、7、9時,平均需要多少次猜測才能猜出它的最小約數?對於這個子問題,我們同樣發現,由於最小約數為3的概率較大,因此直接問「最小約數是3嗎」更好。採取這種策略,我們可以看到:當我心裡想的數是2、4、6、8、10中的乙個時,只需要一次猜測;當我心裡想的數是3或者9時,需要兩次猜測;當我心裡想的數是5或者7時,一共需要三次猜測。因此,採用這種策略平均需要(5*1 + 2*2 + 1*3 + 1*3)/9 = 15/9 ≈ 1.67次猜測。
覺得上面的圖是不是很熟悉?當你把上圖從下面倒著往回推時,你會發現這是乙個經典的貪心演算法問題。我們把擁有相同最小約數的數放進乙個集合,則得到的四個集合分別為、、、。把兩個集合合併成乙個大集合,直觀意義就是這兩個集合是由乙個大集合通過一次詢問劃分出來的,此時總的詢問次數就增加了兩個集合總的元素個數那麼多。借用類似於huffman編碼的演算法,我們立即想到,不斷合併當前元素個數最少的集合,得到的總猜測次數就應該是最優的。利用mathematica求解原問題,我們可以得出,對於2到166的情況,平均494/165=2.9939…≈3次詢問就能找到那個最小約數。
當你聯想到了huffman編碼時,你會驚奇地發現,原問題完全等價於huffman編碼問題。注意到「猜到最小約數」的意思就是說,每乙個可能的答案都對應著乙個yes/no序列(也就是乙個01串),且任一串行都不能成為另乙個序列的字首。而這些最小約數的頻次是不同的,因此我們需要給所有可能的最小約數進行二進位制編碼,使得它們的加權長度最短。這就是乙個典型的huffman編碼問題了。
貪心演算法適用條件 五大常用演算法之三 貪心演算法
一 基本概念 所謂貪心演算法是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,他所做出的僅是在某種意義上的區域性最優解。貪心演算法沒有固定的演算法框架,演算法設計的關鍵是貪心策略的選擇。必須注意的是,貪心演算法不是對所有問題都能得到整體最優解,選擇的貪心策略必須...
經典貪心演算法 貪心演算法概述
貪心演算法具有最優子問題結構,它的特點是 短視 每次選擇對當前局面最有利的決策,來一步步獲得最優解。我個人認為,貪心不是乙個具體的方法,而是一類方法,貪心演算法的關鍵不在於想到,而在於正確性的證明。要證明乙個貪心演算法是正確的,需要證明我們可以把乙個最優解逐步轉化為我們用貪心演算法所得到的解,而解不...
演算法 貪心演算法
把乙個複雜問題分解為一系列較為簡單的區域性最優選擇,每乙個選擇都是對當前解的乙個擴充套件,知道獲得問題的完整解。在解決問題的策略上目光短淺,只根據當前已有的資訊做出選擇,而且一旦做出了選擇,不管將來有什麼結果這個選擇都不會改變。換言之,貪心法並不是從整體最優考慮,它所做出的選擇只是在某種意義上的區域...