我想看我部落格的還是學生人群偏多吧,本身很快就要去面試了,在這篇部落格的問題中,我們就把自己當作boss過把癮。
某天,你想雇用一名演算法工程師。當然,不可能讓你這個boss親自去到處練習應聘者,而是選擇了中介。雇用中介每天都會給你推薦乙個應聘者(ps:還是讓自己輕鬆點,一天只應聘乙個人哈)。是個地球人都知道,你必須要給中介付一小筆錢。然後如果你雇用了乙個應聘者則需要更多的錢,一來你要解雇現有的演算法工程師,更重要的是你要付給中介一大筆錢。在這個問題中還有乙個關鍵的問題,雖然有些不合情理——只要遇到更好的演算法工程師,你都會把之前的給解雇掉(忽略合同等等哦)。
相信大家一看這個問題就知道重點是什麼了,錢,錢,錢,還是錢。你希望費用是最低的。
那麼解決這個問題的邏輯呢,當然就是:
1)從1到n個應聘者中不斷地面試
2)如果當前應聘者比上乙個更好,則雇用當前應聘者並解雇上乙個雇用者
問題是如何將實際問題轉換成偽**,偽**才是最重要的,有了它你便可以將其改成任何語言的描述。
hire-algorithm-engineer(n)
1 employee=0
2for
i=1 to n
3 interview candidate i
4if candidate i is better than employee
5 employee = i
6 hire candidate i
相比大家都看過該系列的前兩篇演算法博文呢吧?這一篇和前面兩篇的區別在於問題的角度不同了,以前我們考慮執行時間,現在我們考慮雇用所花的費用。
大家想想這和前面用到的歸併排序有哪些相似點呢?
不管是執行時間,還是花費費用,在演算法之中都是由一些操作來執行的,所以終究還是逃離不了演算法的分析。
如前所述,假定總共有n個人需要面試,有m個人最終被雇用。面試乙個應聘者時需要給中介的費用是小的,設為cs
;而在你面試通過了這個應聘者後給中介的費用才是大的,設為cb
。所以這個演算法總共要花費的費用為o(
csn+
cbm)
。大家應該有很清晰的理解這個問題吧?為什麼最終由m個人被雇用而不是1個人被雇用呢。原因是這樣的:比如說你現在面試了乙個應聘者,你覺得他蠻優秀的,但是在10天你又遇到了乙個更加優秀的,於是你便辭退了先前的雇員,聘請了最新看中的應聘者。
所以說,無論如何我們都會面試n個人,總費用cs
n也是固定的,真正對演算法有著深遠(波動)影響的應該是這雇用的m個人。
這個是時候,我們就按情況的不同作具體分析了。
很顯然,如果這些應聘者按優秀程度(僅僅是舉個例子)來遞增順序進行面試,最優秀的最先面試,那麼你在應聘這個方面所花費的價錢就僅僅是cs
∗1了。相反,如果是按照遞減順序進行面試,那優秀的最後面試,那麼這下麻煩可大了,你所花費的價錢就是cs
∗n,如果n特別大那就更加糟糕了。
如果大家理解了上面的描述,那就相當於理解了最壞情況分析。
在這個演算法中,我們顯然不可能每次都去強制控制它的輸入,因此便有了隨機演算法這麼一說。
所謂的隨機演算法,就是使用排列的順序隨意。選取乙個主元,輸入的順序便不重要了。無論所提供的輸入是遞增排序還是遞減排序,亦或是沒有排序,都對演算法沒有影響,因為輸入是什麼根本就不重要了。我們都會將其打亂,讓它們隨機分布。
既然選擇了這個演算法,自然有它的優點:
1)它的執行時間不依賴於輸入序列的順序
2)無需對輸入序列的發布做任何假設
3)無論是怎樣的輸入都不會引發最差的運**況
4)而最差的情況卻是由隨機數產生器決定的
那麼什麼樣的演算法是隨機的呢?
其行為不僅由輸入決定,而且也有隨機數生成器產生的數值決定,這種演算法就是隨機的。
話說回來什麼叫做隨機數生成器呢?
隨機數生成器random,通過呼叫random(a,b)而返回a到b之間的整數且每個整數都以等概率出現。
然而許多程式設計環境/語言都會提供乙個偽隨機數生成器(比如說c#裡面的random),它其實是乙個確定性演算法,只不過其結果在統計上看上去是隨機的。
在分析隨機演算法時,和前面的就有區別了。我們開始以執行時間的期望值來衡量,而輸入值也通過隨機數來生成。所以隨機演算法的執行時間也叫做期望執行時間,因為這一切都是不確定的,所以我們只能期望,期望,期望。
如果乙個演算法的輸入是概率分布的,那麼就分析其平均情況執行時間;當演算法本身對於輸入可以通過隨機過程來選擇,那麼就分析其期望執行時間。
我們不是假設輸入的乙個分布,而是設定乙個發布。也就是說在這個演算法開始前,先隨機化它的輸入,讓這些輸入擁有等可能的出現概率。
每次執行這個演算法時,執行都依賴於隨機選擇,所以執行很和前面的不同。因此變有了前面」無論是怎樣的輸入都不會引發最差的運**況「的優點。
所以對於前面的偽**唯一需要改變的只是增加」隨機化應聘者序列「這一段。
randomized-hire-algorithm-engineer(n)
1 randomly permute the list of candidates
2 employee=0
3for
i=1 to n
4 interview candidate i
5if candidate i is better than employee
6 employee = i
7 hire candidate i
那麼問題來了,偽**中的第1行該如何實現呢?還記得鍵值對麼,這是我一開始覺得比較牛叉的概念,後來發現也不過如此。這裡我們就可以用到這個理念。
我們給陣列中的每個元素賦乙個優先順序,優先順序和陣列中的元素都是數字。以往我們給陣列中的元素排序都是直接按元素的大小進行比較、排序的,這裡則跑開了元素本身,通過元素對應的優先順序來比較,優先順序優先的數即更小,我們也可以將其排在後面。
sort-by-priority(a)
1 n=a.length
2 let p[1...n] be a
newrandom array
3for i=1
to n
4 p[i]=ramdom(1,n^2)
5sort a, using p as
sort
keys
這裡我們將優先順序是範圍設為了1到n2
,其實只是為了擴大它的範圍以不至於優先順序重疊,你當然也可以設定為n的三次方,或是4次方。
演算法 由0 5隨機數設計0 8隨機數
首先生成兩個0 5的隨機數a和b。由a和b組成兩位六進製制數ab,00 55 由於a和b都是隨機的,則00 55範圍內的數也是隨機的 將ab化成十進位制c a 6 b。將出現整行的模9,未出現整行的過濾掉即可。00 55 六進製制 0 35 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
演算法導論筆記 05隨機問題
4 用random 0,1 實現random a,b 這道題的實現思路 這個題目相當於在能隨機生成 0,1 的前提下,要求隨機生成 n b a 1 個整數。1 把要生成的數標記為 a,a 1,a 2,b a 1,b 1,b 2 取最小的 m,使得2 m n 3 通過隨機生成 0,1 的函式生成乙個 ...
隨機選擇演算法相關問題
給定乙個整數組成的集合,集合中的整數各不相同,現在要將它分為兩個子集合,使得這兩個子集合的並為原集合 交為空集,同時在兩個子集合的元素個數n1與n2之差的絕對值 n1 n2 盡可能小的前提下,要求他們各自的元素之和s1和s2之差的絕對值 s1 s2 盡可能大。求 s1 s2 使用隨機選擇演算法的原理...