系列的前兩篇中,我們首先介紹了準備工作、學習資源和基本的刷題原則,這些內容特別適合初學者或希望減少刷題壓力的讀者。畢竟我也不喜歡刷題😂

接著,在第二篇裡,我們討論了如何使用 AI 工具(我設計的 GPTs)來提高刷題效率(或說提高「意願」),以及使用 AI 輔助刷題時的一些重點與注意事項。

如果你還沒看過前兩篇,建議可以先看看,會對整個學習脈絡有更清楚的理解。

系列:我的 LeetCode 刷題之道

本文將聚焦於刷題過程中的筆記環節,採取簡單、實用的筆記方式,讓你的學習過程更有條理,並在複習時更加輕鬆。

話不多說,讓我們開始。


為什麼要做筆記?

學習是否一定要做筆記?不同的人有不同看法。我也遇過很厲害但不太做筆記的人。

保哥在其臉書發文中提過:

這段內容讓我最有感觸的是「只有不到 1% 會重看一次」,你也有類似經驗嗎?

我學習時幾乎都會做筆記。不過,不得不承認,「做了卻沒複習」這件事也很常發生。

而且我覺得,筆記如果沒有被複習,那其實和沒做差不多——都是船過水無痕。

所以,筆記建議不要寫太多、太長,組織上也不要太複雜,夠用就好。

延伸閱讀:為什麼你「不需要」所謂的人生管理系統

我的 LeetCode 筆記法相對簡單,沒有使用任何專門的筆記軟體,只是將程式碼和筆記緊密結合在一起,放在 Git repo(repository)中。

接下來,我將分享具體的做法、思路與注意事項。


Git Repo 介紹

把刷題筆記放在一個 repo 中,是「簡單筆記」的第一步——可能是最重要的一步。

我將所有寫過的 LeetCode 題目與筆記放在一個 Git repo 裡,並同步到 GitHub,名為「Grind-75」。

這個名稱顯然是「致敬」第一篇提到的刷題清單「Grind 75」,同時也是期許自己刷個 75 題就好。

Repo 的結構非常簡單,如下:

1
2
3
4
5
6
7
8
9
10
11
12
.
├── README.md
├── pyproject.toml
└── solutions
├── 1. Two Sum.md
├── 1. Two Sum.py
├── 102. Binary Tree Level Order Traversal.md
├── 102. Binary Tree Level Order Traversal.py
├── ...(中略)
├── 973. K Closest Points to Origin.md
├── 973. K Closest Points to Origin.py
└── 98. Validate Binary Search Tree.py

每道題目都會有一個同名的 Python 檔案。(我用 Python 刷題)

此外,複習時會再建立一個同名的 Markdown 筆記,補充更多內容。兩者的搭配構成了我的筆記總合。

這樣的組織方式有幾個好處:

  1. 檔名與題目名稱一致:能快速定位到需要查看的題目。
  2. 版本管理(版控):版控的重要性在開發時自不待言,寫筆記倒是還好。主要的好處應該是:要刪內容時可以「大方」一點,反正有 Git!
  3. 相互對照:放在同一個地方,筆記和程式碼方便快速對照。

Git repo 也方便上傳到 GitHub 分享、供他人參考。雖然除了自己應該沒人會想看🤣,但至少是個足跡!


筆記方法與流程

刷題時,我分兩個階段建立筆記。

這些做法目前都還在實驗階段,可作為參考。

如果後續有更新或不同想法,我會再回來修正、補充。

第一次刷題:記錄在 Python 檔中

在第一次刷題時,我的重心在於「理解」。此時大部分時候都不是我獨立完成答案,而是與 AI 協作。

在這階段,我會將筆記以「程式碼註解」形式寫在 Python 檔裡,格式有兩種:

  1. 使用「單行註解」記錄重點:說明解題意圖、做法,或需要特別注意的細節。
  2. 使用「多行字串」記錄長筆記:例如思路分析或 AI 提供的重要觀念。

範例如下,來自「102. Binary Tree Level Order Traversal.py」:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 使用 BFS 進行層序遍歷 + queue
# 這過程和爬蟲一個網站非常像
class Solution2:
def levelOrder(self, root):
levels = []
if not root:
return levels

# 初始化佇列,將根節點加入佇列
# XXX 這裡使用 list 來模擬 queue,在移除第一個元素時,效率較低
# 可以使用 collections.deque 來實現,移除時則使用 popleft() 方法
# queue = deque([root])
queue = [root]

# 開始 BFS
while queue:
...

我會適時使用「XXX」這類 Code Tags 來標註特別重要的部分。如上述第 10 行。

第一次複習:建立 Markdown 筆記

當我第二次接觸這道題目(第一次複習)時,會再新增一個 Markdown 檔案,進一步補充筆記內容。

這些 Markdown 筆記通常包括:

  • 和 AI 的關鍵環節問答
  • 具體的易錯點分析。
  • 自己對解題的額外補充或心得

範例如下,取自「567. Permutation in String.md」:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 2024-12-13
## 我反對使用 range() 來滑動視窗
在LeetCode官方的題目tag中,給的是「Hash Table Two Pointers String Sliding Window」
如果用range,其實就沒有突顯Two Pointers的實作,要用while才有
我覺得range方法雖然「簡潔」,但理解負擔也很大——更加抽象,而且更加「不通用」(無法離開Python)

## ChatGPT
你說得非常有道理!在 **LeetCode 官方標籤** 中,明確提到 **Two Pointers**,但如果我們使用 `range` 搭配索引來寫,雖然程式碼簡潔,但這種寫法:

1. **沒有突顯 Two Pointers** 的概念:雙指標本質上是維護兩個獨立的索引來滑動視窗,而非透過單個索引來完成。
2. **抽象度較高**:對於初學者來說,`range(len(s1), len(s2))` 的邏輯並不直觀,理解它為什麼能模擬視窗移動較為困難。
3. **不通用**:這種寫法過於依賴 Python 語言特性,無法直接轉換到其他語言(如 C++、Java)。

...(下略)

Markdown 的內容通常會比較長,而且會標註日期——即複習日。

這份 Markdown,就是傳統意義上的筆記,和程式碼放在一起。


筆記的價值與兩難

話說回來,這些筆記,我日後真的都會回去看嗎?

就像前面引用保哥的那段話,說真的,我自己也不敢肯定。

但可以確定的是,當我要複習時,這些筆記能讓我快速回復記憶、重新建立大腦的答題情境

考慮到「筆記愈長,複習意願愈低」的人性,我們應盡可能只記錄關鍵部分,避免未來回顧時需要費力過濾內容。

隨著刷題的進展與對一些概念的熟悉,不需要的筆記也要狠心將其刪除

這正是為何要在 Git repo 中寫筆記——你可以大膽刪內容!


常見問題

以下幾個常見問題,是我在過程中反覆思考過的部分。

為什麼不使用筆記軟體?

雖然我是筆記與筆記軟體的重度用戶,但我認為在刷題情境下,筆記最好直接和程式碼緊密結合即可。

如果把筆記放在 Notion、Logseq 等工具中,程式碼、筆記間的對照會變得麻煩,間接影響複習意願。

為什麼要分成兩種筆記?

因為程式碼註解主要用於記錄細節和立即的想法,而 Markdown 則整理較完整的思路與學習心得。

兩者各有擅長與不擅長之處:

程式碼註解 Markdown 筆記
優點一 通常簡短有力,適合即時記錄 排版多元,可讀性遠高於註解
優點二 直接與程式碼結合 格式完整、方便編輯
缺點一 排版弱,不適合稍長或頻繁換行的內容 必須和程式碼兩兩對照
缺點二 太多註解會影響程式碼閱讀 筆記容易長篇大論、失焦

這種分工讓筆記更有條理,也更容易維護。

還能更簡單嗎?

Markdown 筆記能不能併入程式碼?比如用多行註解取代。

可以是可以,但我認為分開的好處大於合併

首先,程式碼應盡量保持簡潔,過多的註解會影響閱讀;其次,Markdown 更適合整理筆記,哪怕只是排版上的「換行」,也比註解方便許多。

此外,分開管理也讓我們能更靈活地調整和刪減筆記。

如何確保筆記品質?

做筆記時很容易想要追求完整、多多益善,這是筆記愛好者的通病,我也不例外😷

有一個簡單暴力但有效的方法:限制 Markdown 筆記的行數上限!

我目前的想法是:

  1. Easy:上限 100行。
  2. Medium:上限 200 行。
  3. Hard:上限 300 行。(實際上我沒有打算寫 Hard 題😅)

超過上限就要刪減內容!(這裡留有一個餘地:你可以一行寫長一點XD)

這些數字是否適合,要實驗一段時間後才知道。但可以確信的是:有上限絕對比沒上限好得多


結語

本文分享了我在刷題時的筆記方法。這套方法雖然簡單,卻能幫助我們梳理學習思路,同時避免筆記變得過於冗長。

本系列一直將刷題視為一種學習方式,而不僅是通過面試的手段。

至於怎麼樣的方式適合自己,需要一定的嘗試與調整。這也是我寫這個系列的初衷——希望能讓刷題變得有趣、有多元價值。

但願我們都能在這個過程中,找到一點屬於自己的成就感。

下一步

系列的下一篇,我會分享我如何複習這些筆記——畢竟筆記就是拿來複習的。

這部分都還在持續實踐與構思中,敬請期待。