banner
amtoaer

晓风残月

叹息似的渺茫,你仍要保存着那真!
github
telegram
email
x
bilibili
steam

GoLand 的完美 leetcode 刷題體驗

大概從大二開始,我開始陸陸續續地刷一些 leetcode 題,最開始是用 java,之後很長一段時間在用 go。在刷題的過程中,我的刷題方式發生了很大的變化。

最開始是使用 leetcode 的在線編輯器刷題,題目極其簡單還好,稍微複雜一些需要引庫,在線編輯器的自動補全能把人逼瘋... 沒多久,我就棄用了這種最原始的刷題方法。

一個小提示:參加技術招聘時的筆試有很大可能是在網頁編輯器中作答的。

平常不使用在線編輯器刷題主要是為了方便,但也不要因此變成離開 IDE 後就不知所措、標準庫方法名都忘記的工具型選手!

拋開在線編輯器,能想到的方法當然只有在本地編程了。最開始是 vscode + golang 擴展,每次都要:

  1. 新建代碼文件,命名為題目名稱;
  2. 打開 leetcode 題目描述,把代碼模板粘貼下來;
  3. 實現算法,複製粘貼到 leetcode 在線編輯器中,提交測試;
  4. 如未通過則重複 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 忽略該文件信息:

  1. 在源碼文件名前加入下劃線_
  2. 在源碼文件內寫入 //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){
    
}

在文件中實現算法、並在本地調試的例子如圖所示:

rBAAdmL9Ho-ATTS6AAmiD_GXDZ0282

至此該方案已經比較完美了。

舊代碼倉庫的遷移#

原有的代碼雖然不會繼續調試了,但仍然有保留價值。我選擇把它們整理成相同的目錄結構。

  1. 按上述流程設置 leetcode editor 插件。

  2. 克隆原有的平鋪型代碼倉庫,將所有的代碼以及.git文件夾整個移動到$DIR/leetcode/editor/cn/

  3. 寫一個簡單的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')
    
  4. git add & git commit & git push

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。