跳至主要内容

[ALG101] 先別急著寫 Leetcode

在準備刷題找資源時, 看到了 [ALG101] 先別急著寫 leetcode | Lidemy 鋰學院. 這是胡立製作的一系列免費課程, 談刷題之前有些技能是要學會的, 不然會大幅影響刷題所獲得的經驗值ㄡ.

看完課程簡介和程度測驗後, 程度測驗大部分的題目都可以順利完成, 程度上來說是不必要上這課程的. 但覺得已經好久沒靜下來慢慢消化一套課程, 是個收斂心情的練習. 所以還是決定把課程走完, 練習題一一完成, 再刷題.

Unit0 課程簡介

這單元內容其實和課堂簡介差不多. 令我感興趣的是練習題的題目說明, 關於輸入的正整數, 定義很嚴謹. 是個我很容易覺得一般人都會知道, 不會花心力特別定義的地方. 也是我最容易疏忽的地方.

Unit1 要學好程式,從不要寫程式開始

  • 對於程式 / 題目
    • 有些人用想的就解的開:
      • 解開效率很好
      • 解開了但很慢
      • 想到了,但寫不出來
    • 另一些人想不出來解法 (其實和想得到卻寫不出來一樣)
  • pseudo code: 用抽象概念來表示想法, 不拘泥於程式語言
    • 思考解法, 不寫任何程式碼
    • 把想法寫成 pseudo code
      • 一個個可執行步驟
      • 跳轉重複步驟
    • 轉換 pseudo code 為程式碼
  • 簡單的 FizzBuzz 藏有 深度(google 面試題)

Unit2:寫程式之前,先學會「看程式」

  • 看懂程式碼, 學會像電腦一樣思考
  • 把程式執行每個步驟順序寫下, 一步步驗證是否和自己想法一致
  • 善用 debugger 工具, 觀察變數變化和執行流程等, 驗證程式執行和自己想法是否相同,

在國高中參賽時, 很常進行類似這單元的思考練習. 令我印象深刻的倒是課程實戰練習的講解部份, 敘述相當詳盡. 是我很沒耐心去落實的動作, 該好好看齊.

Unit3:寫程式前的最後一步:看懂題目

認真該打屁股, 這個單元主要談需仔細理解程式規格書, 也就是細心看題目和輸入限制等. 因此範例作業題目相當簡單, 重心在細心處理輸入部份.
而自己在範例和作業時犯的錯誤. 還是粗心下未好好閱讀題目限制等. 這點無論刷題或日後工作, 都是該避免的.

Unit4:主角總是最後才登場:寫程式囉

終究本課程中的題目對我還是太簡單, 在練習耐心聽課和一一解題之餘, 同時也練習著從數學 / 語言特性 / ...等地方著手, 如何寫出更有效率的程式.

而有些題目拆成功能函式後, 能做的最佳化反而有限. 以 1021 這題來說, 其實只需一個迴圈就可以解出, 但拆解後, 反而要雙重迴圈才能解. Global optimization 和 Local optimization 的取捨, 政治語言來說, 水很深. 回頭看這些基本題目, 還是有收穫的.

Unit5:經典題目解解看

題型太過簡單直覺, 解題中出現失去耐心及粗心情況. 培養耐心和細心, 是所以花時間作初學者課程訓練的主因, 這點還很需加強.

有趣的是, 實務經驗愈多, 對題目的想法越有所不同. 以 OOXX 來說, 最早會暴力法列出八個判斷式, 後來會想辦法用迴圈解, 現在回頭解, 反而選擇報立法陳列. 貪圖他所節省下來可能積少成多的效能.

Unit6:內建函式做做看

這單元所選的內建函數練習題要實作的話都很簡單, 當然實際上這些內建函式功能還比單元練習複雜得多. 而內建函式實作上會有斷地更新, 在實務需求積累的經驗調整改善. 特別對 JavaScript 來說, 內建函式和自己實作, 還會有 Native libary 和 JIT 的效能差異. 了解並有能力自己實作內建函式的功能是一回事, 工作實務應該還是使用內建函式居多.

Unit7:國中題目大挑戰

要特別題一下搭電梯這題, 後來的習慣是解提前, 會先思考題型的數學解, 再思考演匴法解. 列出數列尋找規格時, 發覺題目其實是費氏數列. 只靠演算法求解的話, 費氏數列用迴圈或遞迴各有時間和空間複雜度上的優勢. 但列規則時, 覺得應該還有 Fn = F(n-1) + F(n-2) 之外的函式可能. 上網查了下, 果然還有其他遞迴函式解法, 可將時間複雜度從 O(n^2) 降到 O(logn), 兼顧時間和空間複雜度. 推演過程日後該找時間深入了解.

最後的解法混用了迴圈窮舉和遞迴. 當 n 數值小的時候, 直接透過窮舉即可. n 較大再透過遞迴增加效率. 小技巧是迴圈窮舉運算得到的數值可以快取, 後面程式呼叫時就不需要重複運算. 一些語言中透過 static 宣告變數, 以保存變數值. JS 函式中變數不支援 static, 但 JS 中函式就是個物件, 可以直接宣告物件成員即可.

其他題目倒是引發沒有太多記憶點, 很入門的練習.

Unit8:初學者只管拿分,誰管你什麼效率

實務上, 時間複雜度和空間複雜度之外, 影響效率的還有運算式本身運算速度. O(C1 * N)+ O(C2 * logN) 理論上後者複雜度大. 但若 C1 >> C1 >> N 則前者效能會更好. 實務上除了考慮演算法複雜度外, 還需考慮使用情況與和各種邊界條件.

Unit9:未來的路還很漫長,你還差得遠呢

多年經驗後回顧基礎課程, 有很多不同想法. 有些題目看似簡單, 深入後其實相當有趣, 偶爾也覺得自己數學理論的不足. 也藉此檢視, 這些基本的題型中, 常見的犯錯不外乎對題目規定了解不足, 邊界條件思考不周, 以及偶爾的 typo 等. 都是些基礎低級錯誤, 該戒慎.

See Also