iT邦幫忙

2021 iThome 鐵人賽

DAY 2
1
Software Development

LeetCode 雙刀流:Python x JavaScript系列 第 2

LeetCode 解題的思考策略與解題地圖

什麼時間點該考慮 LeetCode 刷題?

▶「你有聽過「白板題」嗎?你知道技術考試在面試時會用什麼形式出現嗎?」

How to: Work at Google — Example Coding/Engineering Interview

這張圖是來自 How to: Work at Google — Example Coding/Engineering Interview ,由 Google 分享的的 Mock Interview 過程。技術面試這是許多人在面試前會有的焦慮,而透過刷題是用另一種「技術測驗」方式,讓我們習慣從題目來理解技術的過程。一般來說,技術面試題有兩種考法:「線上/紙本技術面試測試(前測)」或「白板題(現場)」。線上/紙本技術面試測試著重的是「結果」,單純就看最後的分數過不過作為最低的篩選門檻;而現場白版題著重的是「過程」,除了解法之外還有當下的思考脈絡與持續優化的過程。

但是思考脈絡與持續優化都不是可以短期惡補的,需要的是長期的訓練與培養。因此,我不建議只把 LeetCode 當成是面試前的速成班,應該要視為長期持續練習的一種途徑。所以如果在寫程式的過程中有以下兩種狀況,那就很值得思考是否該適合踏入刷題的世界:

  • ① 準備面試的階段
  • ② 想寫出更好的程式

而在刷題的過程中訓練的是「對於解題手法的想像力」,解法就是像是你的武器,當你面對一個問題的時候你可以拿出幾種武器取決於你的經驗與積累。所以對初學者而言首先要求的是寫出可以動的程式,可是當遇到「效能」或是「更複雜的問題」時,這些技巧就成為你無形之中的優勢。總而言之,我覺得刷題的重點是要找到一個適合自己的節奏,刷幾題不是重點,重點是你從每一題中掌握了多少學到了多少而且持續的變強。

幾種解題的策略

LeetCode 題目中從早期的 200 多題,到現在已經有 1000+ 題以上,刷題的難度也大大提升。對於剛開始嘗試要開始刷題的時候通常未遇到以下盲點:

  • 不知道 從哪一個題目開始?
  • 不知道 要解多少題才夠?
  • 不知道 是否真的理解?

而這些問題的背後,都是來自於不知道該如何有效刷題的焦慮感。

如何高效刷題,正確的解題順序

早期坊間都會流傳一些「只要刷滿多少題,就能夠通過某某公司技術面試關」的江湖傳言,不過隨著題目量與日俱增,透過「刷好刷滿」的解題策略早已難以落實。因此,在 LeetCode 題目越來越像題海的同時,單純地大量刷題策略反而會造成反效果。以下整理幾種在不同情境時適合的刷題策略:

① 時間有限的話,從「熱門題」開始刷

熱門題指的是的是那些「面試」時常出現、面試官愛考的題目,在 LeetCode 中也有針對不同公司推出熱門題組組合。所以如果你時間有限且方向明確的情況下,這是一種短期的策略。

② 搭配理論課程,從「分類題」個別刷

如果你還是學生或是正在讀程式設計、資料結構、演算法之類的理論課程,那麼你可以搭配 LeetCode 中的題目分類,針對目前進行的章節選擇相對應的題目進行刷題。理論課程教你的語法及歸納後的方法,更需要搭配實作練習才能學得好。

③ 長期持續鍛鍊,從「難易度」逐步刷

最後一種是將 LeetCode 當成是一種長期持續練習題庫的話,那我建議打散熱門與分類這兩個的維度,從無差別的方式進行刷題,把重點放在「解題」的過程中。雖然說無差別,但還是需要有個順序進行,不然一開始遇到難題就卡關怎麼辦。因此,我們會議可以使用 LeetCode 提供的「難易度」與「通過率」兩個指標排序,從簡單且很多人都通過的題目慢慢往比較難的題目開始逐步進行。

刷題的四個階段

除了「解題順序」之外,如何最大化一個題目的效益也是刷題過程中重要的關鍵。比起一題解完就換下一題這樣的方式,我們更建議花多一點在一個題目中,盡可能地持續迭代、持續優化並且思考沈澱,讓你從一個題目掌握到更深更廣的效益。就如同我們前面所講的,刷幾題不是重點,重點是你從每一題中掌握了多少學到了多少而且持續的變強。

動手之前先思考 → 初探直覺解 → 刻意優化 → 舉一反三

接著當開始進入「一個題目」的解題過程時,我會建議可以分成幾個階段:

動手之前先思考

快速讀完題目知道,先確保題目的 Input、Output 與要求分別是什麼之後。請先不要就貿然的開始寫程式碼,應該是先思考一下大概的解題步驟以多想幾種不同的策略,這個時候可以搭配虛擬碼(pseudocode)或程式流程圖輔佐。

初探直覺解

第二步就可以嘗試把剛剛想到的策略付諸實現,我會建議可以先從「直覺解」、「窮舉法」甚至是「暴力法」開始著手,在不要考慮效能的情況下先求可以邏輯正確可以跑出答案即可。

刻意優化

產生完第一個解法之後,接著就可以從直覺解當中進行重構(Refactoring),嘗試從原本的解法中挑出可以優化的地方來改進。一般來說,程式的優化可以分為「更精簡的程式碼」或「更快地執行速度」兩個角度下去著手。但一個題目能不能馬上想到可以優化的空間,在剛開始是需要「刻意」練習的,有時候可能比想像中更困難。因為腦袋的思考會有先入為主的觀念,有時候不容易跳出既有的框架。所以我會建議這段可以不用急,當寫完一個題目之後可以三個小時、三天,甚是是三週之後再回來看同一個題目,把它當成新的題目重新解解看,反而更容易寫出不一樣的解法。

以我的經驗來說,一個題目至少可以嘗試到三到五種的解法。這樣的效益比起單純的解之外,更多了一層「迭代優化」的培養。

舉一反三

最後當你從一個題目離開後,可以試著解類似題,並且從這個題目的解法「遷移」到另一個類似題中。在 LeetCode 有很多類似的題目,或是一個題目的進階版。從這樣的練習你,你會默默地發現這些看似類似或進階的題目背後都有一些有趣的轉化,而這個轉化就是在培養能不能「迭代優化」的過程。


嗨,大家好!我是維元,一名擅長網站開發與資料科學的雙棲工程師,斜槓於程式社群【JSDC】核心成員及【資料科學家的工作日常】粉專經營。目前在 ALPHACamp 擔任資料工程師,同時也在中華電信、工研院與多所學校等單位持續開課。擁有多次大型技術會議講者與競賽獲獎經驗,持續在不同的平台發表對 #資料科學、 #網頁開發 或 #軟體職涯 相關的分享,邀請你加入 訂閱 接收最新資訊。


上一篇
LeetCode 是什麼?為什麼要刷題?
下一篇
題目背後的設計思維 - 資料結構與演算法
系列文
LeetCode 雙刀流:Python x JavaScript30
0
TD
iT邦新手 5 級 ‧ 2021-09-17 09:13:16

重點摘錄 :D

對初學者而言首先要求的是寫出可以動的程式,可是當遇到「效能」或是「更複雜的問題」時,這些技巧就成為你無形之中的優勢

WeiYuan iT邦新手 4 級 ‧ 2021-09-17 13:55:28 檢舉

對啊,我覺得初期可以練習逐步優化,不一定要求一步到位

0
TD
iT邦新手 5 級 ‧ 2021-09-17 09:13:44

「再」不要考慮效能的情況下先求可以邏輯正確可以跑出答案即可

在 :p

WeiYuan iT邦新手 4 級 ‧ 2021-09-17 13:55:57 檢舉

感謝大大,已修正!不知道有沒有什麼好用的中文錯字檢查器(咦?

0
Spark
iT邦新手 5 級 ‧ 2021-09-17 20:32:16

『動手之前先思考 → 初探直覺解 → 刻意優化 → 舉一反三』

其實這個有一點像工作時實作 feature 的過程耶
只不過在公司不太能透過做到上面每個步驟來刻意練習。

如果公司步調很快的話,通常一開始可能只能先用直覺解,
等到第二次第三次做到類似的功能就可以使用同樣的方式來思考並適當地做進一步的優化,然後慢慢越來越好

我自己覺得不管是尋找解題方法還是思考 feature 作法,在流程上都有相似的地方
也許這也是一種練習解題對工作上有所幫助的地方吧?

WeiYuan iT邦新手 4 級 ‧ 2021-09-20 23:01:55 檢舉

其實就是 MVP 的概念,先求有再求好這樣 ...XD

0
alincode
iT邦新手 2 級 ‧ 2021-09-27 15:07:45

對於剛開始嘗試要開始刷題的時候通常未遇到以下盲點
->
對於剛開始嘗試要開始刷題的時候通常『會』遇到以下盲點

我要留言

立即登入留言