# LeetCode 練習專案 這是一個用來紀錄與管理 LeetCode 練習的專案,整合 C# 與 Go 的題解、基本測試模板、月度學習日誌,以及一支小工具腳本,協助快速建立新題目與維持一致的結構與習慣。 ## 專案架構 ``` . ├── problems/ # 每題一個資料夾 (NNNN-kebab-case) │ └── 3516-find-closest-person/ │ ├── README.md # 題目說明與解題筆記 │ ├── csharp/ # C# 解法 (dotnet) │ ├── go/ # Go 解法 (go module) │ └── test/ # C#/Go 測試模板與測試檔 ├── utils/ │ ├── leetcode_helper.sh # 建題、更新 README、建立月誌 │ └── run_tests.sh # 全域測試執行器(選擇 C#/Go 或全部) ├── logs/ # 月度練習紀錄 (YYYY-MM.md) ├── templates/ # 檔案模板 (.tmpl) │ ├── problem/ # 建題用模板(README、C#/Go、test) │ ├── problem-template.md.tmpl # 題解寫作指引模板(參考用) │ └── logs-template.md.tmpl # 月誌模板 ├── legacy/ # 舊題或舊結構的紀錄 ├── LICENSE └── README.md ``` 命名慣例:問題資料夾以「4 位數題號 + 題目英文 kebab-case」命名,例如 `3025-find-the-number-of-ways-to-place-people-i`。 ## 需求與環境 - C#: 安裝 `.NET SDK 8+`,常用指令 `dotnet build / run / test` - Go: 安裝 `Go 1.21+`,常用指令 `go build / run / test` - Bash: 可執行 `utils/leetcode_helper.sh` 與 `utils/run_tests.sh` 初次使用請先授權腳本: ``` chmod +x utils/leetcode_helper.sh utils/run_tests.sh ``` ## 常用操作 - 新增題目(自動建立資料夾、README、C#/Go 程式與測試模板) ``` ./utils/leetcode_helper.sh problem <題號> <題目名稱-kebab> <難度> # 範例 ./utils/leetcode_helper.sh problem 1 two-sum Easy ./utils/leetcode_helper.sh problem 3000 maximum-area-rectangle Medium # 顯示說明: ./utils/leetcode_helper.sh --help ``` 建立完成後的結構(示意): ``` problems/NNNN-name/ ├── README.md ├── csharp/ │ ├── Program.cs │ └── csharp.csproj ├── go/ │ ├── main.go │ └── go.mod └── test/ ├── SolutionTests.cs # xUnit 測試 ├── TestProject.csproj ├── main_test.go # Go testing └── edge_cases.md ``` - 建立月度日誌(依模板生成 `logs/YYYY-MM.md`) ``` ./utils/leetcode_helper.sh log 2025-09 ``` - 更新主 README(目前顯示題目統計,後續可擴充自動彙整) ``` ./utils/leetcode_helper.sh readme ``` ## 執行與測試 - 執行 C# 解法: ``` cd problems/NNNN-name/csharp dotnet run ``` - 執行 Go 解法: ``` cd problems/NNNN-name/go go run main.go ``` - 執行該題的測試(同時跑 C# 與 Go): ``` ./utils/run_tests.sh NNNN-name [all|csharp|go] # 也可只給題號: ./utils/run_tests.sh 3025 # 僅跑 C# 或 Go: ./utils/run_tests.sh 3025 csharp ./utils/run_tests.sh 3025 go # 顯示說明: ./utils/run_tests.sh --help # 列出目前可用題目: ./utils/run_tests.sh --list ``` 或分別執行: ``` cd problems/NNNN-name/test dotnet test go test -v ``` ## utils 的用途 `utils/leetcode_helper.sh` 提供三個主要功能,將繁瑣步驟自動化、保持專案一致性;`utils/run_tests.sh` 則統一執行測試。 - problem:根據輸入的題號、名稱與難度,建立一個完整題目骨架 - 產生題目 `README.md`(含題目資訊、思路、測試與筆記段落) - 建立 `csharp/` 與 `go/` 目錄及基本程式碼 - 建立 `test/` 目錄,內含 xUnit、Go 測試模板(統一用 `utils/run_tests.sh` 執行) - 初始化 Go module(`go.mod`) - readme:掃描 `problems/` 題目數量,輸出簡單統計到終端(可再擴充寫回本檔) - log:依 `templates/logs-template.md.tmpl` 生成月誌雛形,方便每日記錄與月度回顧 `utils/run_tests.sh` 全域測試執行: - 用法:`./utils/run_tests.sh [all|csharp|go]` - 可為題號(如 `3025`)、資料夾名(如 `3025-find-...`)、或完整路徑(如 `problems/3025-...`) - 其他:`--help` 顯示說明、`--list` 列出可用題目 - 範例: - `./utils/run_tests.sh 3025`(同時跑 C# 與 Go) - `./utils/run_tests.sh 3025 csharp`(只跑 C#) - `./utils/run_tests.sh --list` 小提醒:腳本內建的模板語言為繁中,可依需求修改 `templates/` 與腳本內容。 ## 模板與筆記 - 題目模板:`templates/problem-template.md.tmpl` - 月誌模板:`templates/logs-template.md.tmpl` 建議每題完成後: - 更新該題 `README.md` 的「解題思路」「測試案例」「學習筆記」段落 - 在 `logs/YYYY-MM.md` 紀錄當日題目、時間、心得與統計 ## Templates 強化(重點) - **Problem 模板新增**: - 先備條件與限制(輸入範圍、是否需要 in-place/排序) - 解法比較(A/B/C)、正確性要點、優缺點 - 乾跑(Dry Run)步驟示例 - API 設計(C#/Go 方法簽名)與常見陷阱清單 - 對拍/隨機測試建議;更完整的邊界清單 - **Logs 模板新增**: - 本月設定(主題/目標/挑戰)與主題覆蓋追蹤 - 連續天數(Streak)與錯誤類型統計 - 困難案例復盤與下月計畫欄位 ## Problem 模板範例(節錄,3516) ``` # [3516] Find Closest Person ## 題目資訊 - 難度: Easy - 標籤: Math - 題目連結: https://leetcode.com/problems/find-closest-person/ - 練習日期: 2025-09-04 - 目標複雜度: 時間 O(1), 空間 O(1) ## 先備條件與限制 - 輸入: x, y, z 為整數;值域小;需比較兩者距離 - 回傳: 1/2/0 表示誰先到或同時到 ## 解法比較 1. 解法A(直接比距離) - 思路: 計算 |x-z| 與 |y-z|,比較大小 - 正確性: 距離等速 → 距離小者先到 - 複雜度: O(1) / O(1) 2. 解法B(無) ## 乾跑 - x=2, y=7, z=4 → |2-4|=2, |7-4|=3 → 回傳 1 ## 實作細節與 API 設計 - C# public int FindClosest(int x, int y, int z) { ... } - Go func findClosest(x, y, z int) int { ... } ## 測試案例 - 邊界: 等距(回傳0)、同點、極小/極大值 ``` 完整寫法可參考:`problems/3516-find-closest-person/README.md`。 ## 測試範例(可直接複製改題名) - xUnit(C#) ```csharp using Xunit; public class SolutionTests { [Theory] [InlineData(2, 7, 4, 1)] [InlineData(2, 5, 6, 2)] [InlineData(1, 5, 3, 0)] public void FindClosest_Works(int x, int y, int z, int expected) { var s = new Solution(); Assert.Equal(expected, s.FindClosest(x, y, z)); } } ``` - Go testing ```go package main import "testing" func TestFindClosest(t *testing.T) { tests := []struct{ x, y, z, want int }{ {2, 7, 4, 1}, {2, 5, 6, 2}, {1, 5, 3, 0}, } for _, tt := range tests { if got := findClosest(tt.x, tt.y, tt.z); got != tt.want { t.Fatalf("x=%d y=%d z=%d want=%d got=%d", tt.x, tt.y, tt.z, tt.want, got) } } } ``` ## 自訂模板 - 直接編輯:`templates/problem-template.md.tmpl`、`templates/logs-template.md.tmpl` - 工具腳本已改為讀取 `templates/` 目錄的檔案生成骨架: - 問題頁:`templates/problem/README.md.tmpl` - C#:`templates/problem/csharp/*` - Go:`templates/problem/go/*` - 測試:`templates/problem/test/*` - 月誌:`templates/logs-template.md.tmpl` 不需修改腳本本身即可客製化模板。 ## 工具清單 - `utils/leetcode_helper.sh`: 管理題目與月誌 - 功能: - `problem <題號> <題目名稱-kebab> <難度>`:建立新題目(產生 `README.md`、`csharp/`、`go/`、`test/` 骨架) - `log [YYYY-MM]`:建立月度學習日誌(預設本月) - `readme`:顯示題目數量統計 - `-h|--help`:顯示說明 - 範例: - `./utils/leetcode_helper.sh problem 3025 find-the-number-of-ways-to-place-people-i Medium` - `./utils/leetcode_helper.sh log 2025-09` - `./utils/leetcode_helper.sh --help` - `utils/run_tests.sh`: 執行指定題目的測試 - 語法:`./utils/run_tests.sh [all|csharp|go]` - 可為:題號(如 `3025`)/ 目錄名(如 `3025-find-…`)/ 完整路徑(如 `problems/3025-…`) - 參數:`--help` 顯示說明、`--list` 列出現有題目 - 範例: - `./utils/run_tests.sh 3025`(同時跑 C# 與 Go) - `./utils/run_tests.sh 3025 csharp`(只跑 C#) - `./utils/run_tests.sh --list` ## 未來可擴充方向 - 主 README 自動彙整各題狀態(難度、語言、連結、完成度) - 加入 CI(如 GitHub Actions)自動跑各題測試 - 更完整的模板與範例(含 I/O、邊界測資) --- 歡迎依個人習慣調整腳本與模板,持續穩定地練習最重要!