演算法 3 由招聘問題看隨機演算法

2022-04-11 01:55:04 字數 3193 閱讀 1033

我想看我部落格的還是學生人群偏多吧,本身很快就要去面試了,在這篇部落格的問題中,我們就把自己當作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 使用隨機選擇演算法的原理...