大概從大二開始,我開始陸陸續續地刷一些 leetcode 題,最開始是用 java,之後很長一段時間在用 go。在刷題的過程中,我的刷題方式發生了很大的變化。
最開始是使用 leetcode 的在線編輯器刷題,題目極其簡單還好,稍微複雜一些需要引庫,在線編輯器的自動補全能把人逼瘋... 沒多久,我就棄用了這種最原始的刷題方法。
一個小提示:參加技術招聘時的筆試有很大可能是在網頁編輯器中作答的。
平常不使用在線編輯器刷題主要是為了方便,但也不要因此變成離開 IDE 後就不知所措、標準庫方法名都忘記的工具型選手!
拋開在線編輯器,能想到的方法當然只有在本地編程了。最開始是 vscode + golang 擴展,每次都要:
- 新建代碼文件,命名為題目名稱;
- 打開 leetcode 題目描述,把代碼模板粘貼下來;
- 實現算法,複製粘貼到 leetcode 在線編輯器中,提交測試;
- 如未通過則重複 3 。
重複性勞動總是讓人煩躁,於是我找到了 vscode 中的 leetcode 擴展,該擴展可在 vscode 中展示題目列表,選中題目後自動在 vscode 中預覽題目並生成文件描述和模板到指定文件夾。這在很大程度上節省了我的工作量。
然而,隨著某次 go 或 vscode 的更新,vscode 內對 go 的自動補全檢查擴大到了文件夾級別。(或許是隨著 gomod 的引入?我已經不太清楚了)因為不同題目全部在文件夾的同一級,所有的在不同題目中定義的構造體、函數只要重名就會報重聲明錯誤,而這在一個存儲上百道題解的文件夾中帶來的是毀天滅地的災難。我的源碼文件近乎一半被標紅,每每看到那一片片的紅色波浪線都給我帶來生理上的不適。
現在想來應該多去查查 leetcode 擴展的文檔的,或許有什麼解法也說不定?
時間過得飛快,轉眼間就畢業工作了。雖然工作主要使用的語言是 python,但我平時還是習慣寫寫 go。前段時間幾位同事說要比賽力扣連續打卡一個月,我也順便參與了。這次從 vscode 換成了 goland,我打算一步到位配置一個完美的力扣刷題環境。
以下是我的配置過程及思路:(囉嗦半天總算說到重點了。)
安裝 leetcode 刷題插件#
與 vscode 類似,GoLand 中也有類似的刷題插件,名為 LeetCode Editor。
組織源碼文件夾#
安裝擴展完成後,可在設置中調整 leetcode 題目描述、源碼模板下載到的位置。假設你把位置填成了 /home/amtoaer/Documents/code/
。
隨便點擊一個題目,將會發現實際的目錄結構如下:
# 此時位於 /home/amtoaer/Documents/code/
./leetcode/
└── editor
├── cn
│ └── doc
│ └── content
│ └── 1302.層數最深葉子節點的和
└── en
也就是說,如果使用中文刷題,並把擴展配置中的TempFilePath
設置為$DIR
的話,實際的源碼所在目錄為$DIR/leetcode/editor/cn/
,並且該目錄下還會有一個多餘的doc
文件夾用於存儲題目描述。
如果有保存源碼文件的需求,請到該目錄下尋找。
如果你像我一樣喜歡把題目上傳到 git 倉庫,在/leetcode/editor/cn/
中新建 git 倉庫並在該文件夾下新建.gitignore
,於其中寫入一行:
doc
將題目描述文檔所在的文件夾忽略即可。
解決同文件夾下的命名衝突錯誤#
通過查閱相關資料,我得知在 go 源碼文件中做以下任意兩個操作,可使 go build 忽略該文件信息:
- 在源碼文件名前加入下劃線
_
; - 在源碼文件內寫入
//go:build ignore
。
然而,這兩種方式都有致命缺陷,即在 GoLand 的編輯器頭部有無法關閉的醒目標識,這對於完美主義的我們是不能接受的。
繼續查找資料,發現 leetcode editor 擴展是支持自定義代碼文件模板和路徑的。且 #304 提到可通過在自定義文件名中加入路徑分割符來新建文件夾。
既然平鋪的源碼文件會導致重聲明錯誤,那我們可以給每個源碼文件都創建一個新的文件夾。
首先勾選Custom Template
選項,接著將Code FileName
修改為:
$!{question.frontendQuestionId}.${question.title}/solution_test
這將使文件結構變為:
├── 102.二叉樹的層序遍歷
│ └── solution_test.go
├── 103.二叉樹的鋸齒形層序遍歷
│ └── solution_test.go
├── 104.balabala
│ └── solution_test.go
這時我們已經做到了單個代碼文件的命名隔離。
易於調試#
得益於擴展的自定義代碼模板功能與區域代碼提交機制,我們可以非常簡單地調試我們的代碼。
區域代碼提交:指擴展維護兩條固定註釋,分別作為提交位置的起點和終點,提交時只有這兩個註釋之間的代碼會被提交。
我們可以把調試部分(如單測或者 main 函數)放在提交區域外,這樣不會對提交的代碼有任何影響。
一個簡易的模板如下圖,需將其填寫在 leetcode plugin 配置中的Code Template
項:
package leetcode
import(
"testing"
)
${question.content}
${question.code}
func Test$!velocityTool.camelCaseName(${question.titleSlug})(t *testing.T){
}
這樣只需要把樣例輸入輸出寫在測試函數內,點擊運行即可。
一個依此模板生成的文件如下:
package leetcode
import(
"testing"
)
//給你一個正整數數組 nums,請你幫忙從該數組中找出能滿足下面要求的 最長 前綴,並返回該前綴的長度:
//
//
// 從前綴中 恰好刪除一 個 元素後,剩下每個數字的出現次數都相同。
//
//
// 如果刪除這個元素後沒有剩余元素存在,仍可認為每個數字都具有相同的出現次數(也就是 0 次)。
//
//
//
// 示例 1:
//
//
//輸入:nums = [2,2,1,1,5,3,3,5]
//輸出:7
//解釋:對於長度為 7 的子數組 [2,2,1,1,5,3,3],如果我們從中刪去 nums[4] = 5,就可以得到 [2,2,1,1,3,3],裡面每個數
//字都出現了兩次。
//
//
// 示例 2:
//
//
//輸入:nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
//輸出:13
//
//
//
//
// 提示:
//
//
// 2 <= nums.length <= 10⁵
// 1 <= nums[i] <= 10⁵
//
//
// Related Topics 數組 哈希表 👍 64 👎 0
//leetcode submit region begin(Prohibit modification and deletion)
func maxEqualFreq(nums []int) int {
}
//leetcode submit region end(Prohibit modification and deletion)
func TestMaximumEqualFrequency(t *testing.T){
}
在文件中實現算法、並在本地調試的例子如圖所示:
至此該方案已經比較完美了。
舊代碼倉庫的遷移#
原有的代碼雖然不會繼續調試了,但仍然有保留價值。我選擇把它們整理成相同的目錄結構。
-
按上述流程設置 leetcode editor 插件。
-
克隆原有的平鋪型代碼倉庫,將所有的代碼以及
.git
文件夾整個移動到$DIR/leetcode/editor/cn/
。 -
寫一個簡單的
python
腳本用於遷移源碼:import os files = os.listdir('.') for file in files: items = file.rsplit('.', 1) if len(items) != 2: continue name, extension = items if extension != 'go': continue os.mkdir(name) os.rename(file, f'{name}/solution_test.go')
-
git add
&git commit
&git push