amtoaer

晓风残月

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

The perfect leetcode experience in GoLand

Starting from my sophomore year, I started to solve some Leetcode problems gradually. I initially used Java, but then switched to Go for a long period of time. During the process of solving problems, my approach to Leetcode has undergone significant changes.

At first, I used the online editor provided by Leetcode to solve problems. It was fine for very simple problems, but when the problems became slightly more complex and required importing libraries, the auto-completion feature of the online editor drove me crazy. It didn't take long for me to abandon this primitive way of solving problems.

A small tip: Written tests during technical interviews often require answering questions in a web-based editor.

I don't usually use online editors for problem-solving because it's more convenient, but don't let that make you feel lost without an IDE and forget the names of standard library functions. Be a skilled developer!

Without the online editor, the only option left was to solve problems locally. I started with VS Code and the Go extension, and each time I had to:

  1. Create a new code file and name it after the problem.
  2. Open the Leetcode problem description and copy the code template.
  3. Implement the algorithm and copy-paste it into the Leetcode online editor for testing.
  4. Repeat step 3 if it didn't pass the tests.

The repetitive work was annoying, so I found the Leetcode extension for VS Code, which displays a list of problems in VS Code and automatically previews the problem description and generates the file structure and template in a specified folder. This greatly reduced my workload.

However, with a certain update of Go or VS Code, the auto-completion check in VS Code was extended to the folder level (perhaps due to the introduction of gomod? I'm not quite sure anymore). Since all the different problems were at the same level in the folder, any struct or function defined in different problems would result in a redeclaration error if they had the same name. This was a disaster in a folder containing hundreds of solutions. Almost half of my source code files were marked with red, and seeing those red squiggly lines caused me physical discomfort.

Looking back, I should have read the documentation of the Leetcode extension more. Maybe there was a solution?

Time flew by, and I graduated and started working. Although the main language used at work was Python, I still enjoyed writing Go in my spare time. Recently, a few colleagues mentioned participating in a Leetcode daily challenge for a month, so I decided to join in as well. This time, I switched from VS Code to GoLand and planned to configure a perfect Leetcode environment.

Here is my configuration process and thoughts: (Finally getting to the point after all the rambling.)

Install the Leetcode plugin#

Similar to VS Code, GoLand also has a Leetcode plugin called LeetCode Editor.

Organize the source code folder#

After installing the extension, you can adjust the location where the Leetcode problem descriptions and source code templates are downloaded in the settings. Let's say you set the location to /home/amtoaer/Documents/code/.

If you click on a problem, you will find the actual directory structure as follows:

# Currently located at /home/amtoaer/Documents/code/
./leetcode/
└── editor
    ├── cn
   └── doc
       └── content
           └── 1302.Sum-of-Deepest-Leaf-Nodes
    └── en

This means that if you are solving problems in Chinese and set the TempFilePath in the extension configuration to $DIR, the actual directory where the source code is located will be $DIR/leetcode/editor/cn/, and there will be an additional doc folder in that directory for storing problem descriptions.

If you need to save the source code files, you can find them in that directory.

If, like me, you prefer to upload the problems to a Git repository, you can create a Git repository in /leetcode/editor/cn/ and create a .gitignore file in that folder with the following line:

doc

This will ignore the folder containing the problem descriptions.

Resolve naming conflicts in the same folder#

After researching, I learned that there are two ways to make go build ignore a file in Go source code:

  1. Prefix the file name with an underscore _.
  2. Write //go:build ignore inside the file.

However, both of these methods have a fatal flaw: they display a prominent indicator in the GoLand editor that cannot be turned off, which is unacceptable for perfectionists like us.

Continuing my research, I found that the Leetcode editor extension supports custom code file templates and paths. Moreover, it was mentioned in issue #304 that you can create folders by adding path separators in the custom file name.

Since having flat source code files would result in redeclaration errors, we can create a new folder for each source code file.

First, check the Custom Template option, and then modify the Code FileName to:

$!{question.frontendQuestionId}.${question.title}/solution_test

This will create the following file structure:

├── 102.Binary-Tree-Level-Order-Traversal
│   └── solution_test.go
├── 103.Binary-Tree-Zigzag-Level-Order-Traversal
│   └── solution_test.go
├── 104.balabala
│   └── solution_test.go

Now we have achieved isolation of file names for each code file.

Easy debugging#

Thanks to the extension's custom code template feature and region code submission mechanism, we can easily debug our code.

Region code submission: The extension maintains two fixed comments as the starting and ending points of the submission area. Only the code between these two comments will be submitted.

We can place the debugging part (such as unit tests or a main function) outside the submission area, so it won't affect the submitted code.

Here is a simple template that needs to be filled in the Leetcode plugin configuration under the Code Template field:

package leetcode

import(
    "testing"
)

${question.content}

${question.code}

func Test$!velocityTool.camelCaseName(${question.titleSlug})(t *testing.T){
    
}

This way, you only need to write the sample inputs and outputs inside the test function and click run.

Here is an example of a file generated using this template:

package leetcode

import(
    "testing"
)

//Given a positive integer array nums, return the length of the longest prefix of the array such that it is possible to remove exactly one element and the remaining elements are all equal in frequency. 
//
// 
// If after removing one element there are no remaining elements, it is still considered that every element has the same frequency (i.e., 0 times). 
//
// 
//
// Example 1: 
//
// 
//Input: nums = [2,2,1,1,5,3,3,5]
//Output: 7
//Explanation: For the subarray [2,2,1,1,5,3,3], if we remove nums[4]=5, we will get [2,2,1,1,3,3], which has equal frequency of each element.
// 
//
// Example 2: 
//
// 
//Input: nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
//Output: 13
// 
//
// 
//
// Constraints: 
//
// 
// 2 <= nums.length <= 10⁵ 
// 1 <= nums[i] <= 10⁵ 
// 
//
// Related Topics Array Hash Table 👍 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){
    
}

An example of implementing the algorithm in the file and debugging it locally is shown in the image below:

rBAAdmL9Ho-ATTS6AAmiD_GXDZ0282

At this point, the solution is quite perfect.

Migration of the old code repository#

Although the old code will no longer be debugged, it still has value. I chose to organize them into the same directory structure.

  1. Set up the Leetcode editor plugin following the above process.

  2. Clone the existing flat code repository and move all the code and the .git folder to $DIR/leetcode/editor/cn/.

  3. Write a simple Python script to migrate the source code:

    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

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.