透過上述的說明,你可以明白若進入一個自己不懂的領域,要針對該領域的問題找出適合的演算法來解決問題,這是需要花費時間學習.另外還有一個簡單的分類方式是用實做的方法來進行分類.例如,你的工作安排工廠裡產線的機器,每個機器會有不同的維修周期,不同種類的機器也會有不同的處理量,而產線上機器之間的順序是不會變的,就像一定得先把模具做出來,才能做各式機械加工處理,完成後才能噴塗料等等的程序.你老闆希望你能設計一個機器運作方式讓機器運作的情況是最佳的,也就是說產線的產量是最大的.像這樣看起來就是一個 “最佳化” 的問題,在演算法課本裡面會談到許多最佳化的問題.以這問題來說,採用 linear programming (未來文章會介紹) 是一個可能的解法之一.但要注意的是,並不是所有 “最佳化” 的問題都能用 linear programming 來找到最佳值,上述問題的限制給的很多,因此無形中幫你把問題的範圍縮小,解法也相對變簡單.如果問題的限制變少了,如加工製程的順序是不重要的,拿掉就個限制就讓整個問題變得很難用一個簡單的演算法找到最佳解,難的不是找不到答案,而是一旦問題的輸入量變大 (機器變多),找出解答的時間 (演算法內的步驟) 就會以不成比例的方式往上增加,也就是說演算法的 Big O 變大.用寫程式的角度來看,一旦限制條件變少,程式就必須做更多的步驟來尋找各種可能以得到最佳值,這相當於 for loop 會變多了.Big O 漸漸變大時,此時你就得思考其他的解法方法,如果你的情境不需要最佳解,則採用一些近似解法來尋找接近最佳解的解答,而且通常近似值解法的速度都會比最佳值解法的速度來得快很多.
分類的情況實在太多了,無法一一描述.在這邊希望帶給非電腦科系畢業的資訊人一個觀念就是學習演算法的過程中,要先了解把問題分類,並且也知道一些常見問題分類裡一些著名的演算法.我們不需要發明什麼了不起的演算法,以我個人的經驗是,能夠善用許多聰明人為解決某些問題而想出來的演算法,這就已經夠利害了,同時也能幫助你寫出好程式.畢竟,對非本科畢業的資訊人來說,不是遇到一個不會的問題就用暴力法來解決.即便是一個看似很簡單的工作人員排班表的事情,用暴力法,它的 Big O 可是很大的.又比如你是做地圖導航的工程師,你要安排一個最短路徑從某一個點到另一個點,若沒有好的演算法,你能想像你用暴力法來解決,那將是什麼程度的 Big O 嗎 ?
最後,你可能會問,你明白分類的重要性,則到底有那些分類呢 ? 老實說,我回答不出來有那些分類.通常我的方法是看問題的資料輸入類型和問題的重點來決定.例如,問題是一個最佳化問題,例如找出成績最好的前十名學生,或是訂單金額最高的前十名,資料輸入類型是一個 List 或 Array,一堆資料庫來的訂單或學生清單,而問題的重點是在最佳解,像最大值,最小值,或某些子項目是符合某個條件,這一類的解法通常像之前一些 Coding面試文章的解法那樣.再困難一點,問題是一個觀光路徑排列的問題,資料輸入類型是一個 Tree 或 Graph,像一個地圖,而問題的重點是依照某個條件做排序,例如觀光景點參觀順序從低海拔排到高海拔,此時除了要了解基本的 Tree, Graph 的資料結構運作之外,最後還得讓排序演算法派上用場.不論怎麼分類,其實你都能感受到問題都是傾向某一種 “最佳” 的方向靠近,而且善用好的演算法就是希望結果能快速地被運算出來,也就是 Big O 盡可能低.如果問題不需要傾向某一種 “最佳” 的方向靠近,那麼程式隨便亂寫,最後能跑出答案就行了.
雖然每個演算法都有特定目的用來解決特定問題,不同的問題之間有可能用相同的演算法來解決嗎 ? 答案是有可能的,這是下一篇文章的重點.
Hope it helps,
0 意見:
張貼留言