Sunday, April 13, 2008

Two Ways to Solve a Problem

這些年下來,我反覆觀察到一個現象:程式員各有一套慣用的方法來克服自己遭遇到的問題,這些解題習慣可區分成兩種,工程師多只專精其一,只有少數能任意在兩者間自在地切換。

在很多情況下,無論程式員採用哪種作法,都可輕易把問題解掉;但是另有一些問題,卻不是這樣隨性而為就解得掉的--這就值得我們好好玩味了……

以 1..n 的正整數相加這個例子來說,我知道程式員應該利用現成的副程式,以爬說語來寫,應該要長成這樣:

n = 100
y = sum(range(1, n+1))

假裝我們沒有現成的,像 sum 這樣的副程式可用。那麼,一種可能的寫法如下:

y = 0
for i in range(1, n+1):
    y += i

這是標準的合成(Synthesis)法。以這個例子來說,如果不考慮時間複雜度要 O(n) ,這個方法其實沒什麼不好,畢竟它非常直覺,寫起來也很簡單。

大部分資訊背景的,甚至其他工程背景的,都傾向以這種「合成」的策略來克服問題。

由於這是個已經爛掉的例子,我們當然知道有個時間複雜度只要 O(1) 的作法:

y = (1+n)*n/2

這是典型的以分析(Analysis)手段來解題的例子。通常數學或物理等理科背景的人,比較慣用這種「分析」的手段來解決問題。

大部分的工程問題都牽連太廣、太複雜了,很難找到分析解;所以工程師們很習慣採用 trial and error 的合成策略,只求找到一個可行的作法。

這種「先兜出一個作法,看著它如何失敗,然後再兜另一個作法試試,不行的話再兜另一個……」的合成策略,陪伴我們度過無數個夜晚,也解決了不少問題,但如果每次「歪打」都沒有任何「正著」甚至「歪著」的跡象,這種策略就完全失靈了。

在合成策略無效或顯得白費功夫時,也許可以學著適應理科背景的慣用手法:「靜心分析問題,用數學精確地描繪出問題,建立模型,擴充內容,增大視界」,據此提供新的想法和嘗試的途徑。

推薦文選:

Tags: [] [] []

1 comments:

Wallace said...

我認為工程師風格和個性及所經歷的學習程序有關。
個性上積極性高的人,會先做了再說。
而個性保守的人,會先調查好了再做。
學數學及物理的人,會測試完了再做,因為其學理上是由理論一層層堆起來的。
學醫學及化學的人,總是先投藥做了再說,因為經驗才是真的,新發現是由新組合找到。
所以其實和所面臨的事有些關係才選擇方法。
不過現在面臨的東西複雜了,確實要混合使用。例如做embedded如機器人等,一方面對於使用電腦則要有如數學家一般清楚的頭腦,才會了解那一段程式的功能及分類。一方面又要對付Sensor所給定的不知名狀況,只能先試了抓到資料再分析。動作後又會面臨新狀態。
了解所面對的問題的類別及了解解決問題比較符合的方法,就比較可以在兩者之間做較好的切換。
以上為個人心得,提供參考。