歸併排序 (Merge Sort) 算是比較優秀的排序算法,因為時間複雜度是
O(N log N)
;而選擇排序、冒泡排序、和插入排序時間複雜度則是O(N^2)
。 Merge Sort 的基本思想是分治法 (Divide and conquer),是將原問題分解為規模較小的子問題,然後逐一解決這些子問題之後,合併這些子問題的答案,並建立原問題的答案。
這題是非常有名的 Fibonacci 數列,其特徵是除了前兩個數字之外,每個數字等於前兩個數字之和。解法可以帶出一些經典觀念和想法,例如 :
- Dynamic Programming
- 迭帶 for-loop
- recursion 遞迴
由於 Fibonacci 數列的時間空間複雜度計算比較特別,加上可以很初步引入很多的思考方式,故雖然這題是 easy ,我還是做個紀錄。
遞迴 (Recursion),通過調用自身函數,有時可以將某個複雜的問題,分解為規模較小的子問題。而 Recursion 也經常和以下演算法配合使用 :
- 分治法 divide and conquer
- 回溯法 backtrack
- 動態規劃 dynamic programming
在實際狀況中,遞迴函數的設計常常很難想像,因為遞迴設計屬於逆向思維,在設計遞迴函數的時候,非常容易被這種層層嵌套搞暈,在這裡簡單給個模板範例講解。
在刷 leetcode 時,都會需要分析和解釋一下自己寫的程式的演算法複雜度,基本上主要是解釋 :
- 時間複雜度
- 空間複雜度
從以上兩個面相去分析 code 效率、品質、trade off,本文記錄一些分析要點。另外建議面試的時候,當對題目有想法時,先不用急著直接實作,而是先估出複雜度,並和面試人討論,確認不會 TLE ;空間是否需要優化;符不符合題目要求等等,最後再開始寫。
反轉 Linked List 是一道經典的題目,可以用分別用 :
- 指針 (iterative)
- 遞迴 (recursive)
兩種截然不同的風格來解答。個人認為是蠻好的題目,可以多寫幾次,並從各種不同的解答方式來說明思考,故在此筆記。要說簡單也不算,對於 recursive 解法一開始我覺得有點難理解 ! 雖然被歸類在 Easy,但我私心覺得蠻容易打擊第一次做的人的…
Multiple points 的操作,經常用在 array 或 linkedList 上,有幾點事情可以在刷題時特別注意:
指標會把 list 切成幾個部分,特別注意每一部份的定義
list 是否有排序或可以排序
指標移動是使用快慢指標還是左右指標
會不會改變原本的 list
其中第一點,把 array 切成幾個部分,每個部份的定義,是最重要的思想,可以多思考。