[Algorithm] Day.3 隨機演算法

2023-03-11

#algorithm #note

隨機演算法是一種技巧,在自己的演算法當中加入一些隨機性,目的是為了要提升演算法效能,也就是降低時間或是空間複雜度。 這種演算法的核心概念為 演算法結果源自於一個隨機產生的數字,在重複使用這種演算法之後,他有很高的機率會比一般常用的線性演算法來得更有效率。

隨機演算法的設計通常離不開下面這兩種範疇

蒙地卡羅演算法 (Monte Carlo Algorithms)

蒙地卡羅演算法就是在既定的時間內,利用隨機的方式提供盡可能正確的結果,換句話說利用這個演算法算出的結果可能是錯的,但是他會把錯誤的機率控制在一個非常低的範圍內。

這個演算法最常見的例子就是 求圓周率 的演算法了!

可以想像成當今天我們看不到,但是要判斷一個物品的形狀我們應該怎麼做!答案就是盡可能地摸遍這個物體的每一個角落之後拼湊成出他的形狀。

求圓周率的演算法也是這樣,在座標軸上,利用電腦隨機產生 x 座標在 0 和 1 之間,且 y 座標也在 0 和 1 之間的點,因為座標都在 0 和 1 中間,所以在點在某個區域中的數量會和那個區域的面積成正比,所以只要我們把所有點的數量除以落在圓裡面的點的數量,就可以算出圓周率的數值。

當然因為點是隨機產生的,所以有可能會發生點集中在圓裡面或是圓外面的情況,導致算出來的結果不準確,但當今天我們樣本數夠大之後,就可以把這種不準確的結果降到最低。

拉斯維加斯演算法 (Las Vegas Algorithms)

拉斯維加斯演算法和蒙地卡羅相反,他保證會得到正確答案(或是沒有答案),但他就不能保證演算法的執行時間,不過雖然不保證執行時間,卻可以確保在最差狀況發生時他的執行時間。

這類演算法常常在我們找東西的時候使用。

舉例來說當我們今天要在有 n 個數字的陣列當中找到相同的數字 在這個陣列當中有 n/2 個不同的數字和 n/2 個相同數字

在傳統的演算法當中,我們會一個一個檢查,當找到兩個相同數字的時候回傳

Algorithm findDuplicateGeneral(numberArray) {
  for number in numberArray do
    from numberIndex + i to numberArrayLength do
      if number == numberArray[index]
        return number
        break
}

當這個一個一個檢查的演算法遇到排列非常差的情況就會花費很多時間 例如:[1, 2, 3, 4, 5, 9, 9, 9, 9, 9] 遇到這種排列我們就需要花 n/2 + 2 次才有辦法找出重複的數字是什麼 (n/2 + 1 次都沒有重複,最後再加一次找出重複的是哪個)

但如果我們採用隨機的方式在這個陣列中隨機挑選兩個數字出來比對,大約 20% 的機率會成功找到重複的數字。 換句話說,找失敗的機率大約為 80%;那如果今天連續執行 10 次的話,沒有找到正確數字的機率就會大約是 0.8^10,大約是 0.1,換句話說就是有 90% 的機率會找到正解。 當今天陣列像上面只有 10 項的時候,可能傳統的方式看起來效率會超過隨機演算法,但當今天有 100 個數字或甚至更多的時候,拉斯維加斯演算法就可以很好的幫我們節省時間。

就這個例子我們就可以看出拉斯維加斯演算法雖然不能保證幾執行多少步會成功,但卻可以在一定次數後擁有很高的成功率,且最後一定會給我們正確的答案。

雖然一步一步的執行演算法可以確保執行的結果,但在設計演算法的時候不妨可以把隨機演算法加入思考,讓自己設計出的演算法可以有更好的執行效率。