DSA
The NeetCode 150 in Go: How to Work Through the List on thita
Learn Go idioms for the NeetCode 150 list, practise solutions on thita, and rehearse a spoken coding interview with runnable code. Start practising today.

Practise the NeetCode 150 by pattern
The NeetCode 150 in Go is not a line-by-line translation exercise. Go’s slices, maps, interfaces and standard library create different decisions around ownership, ordering, text and numeric safety. The useful target is the NeetCode 150 list, practised on thita: learn the pattern, choose a Go representation, and explain the trade-offs while you code.
The list contains 150 problems: 28 Easy, 101 Medium and 21 Hard. You can work through the list by NeetCode topic or use thita’s pattern grouping, which organises DSA problems into 99 patterns across 16 families. The NeetCode 150 by pattern lists the problems with their pattern context.
This guide focuses on the Go details that repeatedly decide whether an interview solution is clear: comma-ok map lookups, map[T]struct{} sets, slice aliasing, container/heap, sorting, bytes and runes, strings.Builder, recursive closures and integer types.
Thita is not affiliated with NeetCode.
Why does the NeetCode 150 in Go need a different approach?
Go has a small language and a deliberately explicit standard library. There is no built-in heap, no general-purpose set type and no implicit conversion between strings, bytes and runes. Those choices make the representation visible, which is useful in an interview provided you recognise the right shape quickly.
Start with the invariant rather than the topic label. Arrays and Hashing, Two Pointers, Sliding Window and Stack usually become short loops with carefully maintained state. Trees, Graphs and Backtracking need a clear helper function or closure. Heap problems need an ordering definition and a correct interface implementation. Dynamic programming needs a state type chosen before transitions are written.
A practical loop for each problem is:
- Read the input and state the invariant in plain English.
- Choose the Go representation: map, slice, queue, heap, linked node or tree node.
- Write a correct baseline before discussing optimisation.
- Test empty input, repeated values and arithmetic near the stated limits.
- State time and space complexity after checking what the code actually stores.
The DSA patterns sheet is useful when the list order hides a shared implementation shape. The NeetCode topic remains a useful label, but the pattern tells you which state and operations to reach for.
Which NeetCode topics are easier or harder in Go?
Topics that tend to feel natural
Arrays, hashing, sliding windows, two pointers and many greedy problems fit Go’s compact loops well. A map provides direct lookup, a slice is a practical dynamic array, and for gives you explicit control over indexes and ranges. The zero value of a map lookup is also convenient when a missing key can safely mean zero.
Trees are straightforward once the node type is established. A recursive function can return a value directly, while a closure can capture an answer or a visited set without a receiver. Graph traversal is similarly direct: adjacency lists are commonly [][]int or map[int][]int, and a slice plus a head index is enough for a queue.
Topics that need deliberate Go practice
Heap and design problems require more preparation because Go’s heap is interface-based. You define the ordering and implement the methods expected by heap.Interface. Backtracking has a different trap: slices are descriptors over an underlying array, so an append can reuse storage and change data visible to another branch.
String problems require a conscious choice between bytes and runes. Problems with an ASCII-style alphabet can use bytes for direct indexing; Unicode character positions need runes. Numeric problems need the same care. Go will not silently widen an int expression when you assign the result to int64, so conversion must happen before multiplication or addition.
These are Go-specific interview habits, not reasons to avoid the language. Rehearse the representation before typing the algorithm, especially for ownership, character encoding and arithmetic.
Which Go standard-library pieces should you know cold?
Keep this small toolkit ready:
map[K]Vwith comma-ok lookup:value, ok := table[key].map[T]struct{}for membership when no stored value is needed.slices.Sortfor an ordered slice such as[]int.sort.Slicefor a custom ordering, such as a slice of interval records.container/heapfor priority queues and top-k problems.strings.Builderfor repeated string output.[]bytefor byte-oriented text and[]runefor Unicode code-point indexing.
Know which functions mutate their inputs. Sorting a slice changes its order, and a backtracking function that retains a slice must copy the path at the ownership boundary.
How should maps and sets be used in Go?
A map lookup returns a value and a Boolean. The comma-ok form distinguishes an absent key from a present key whose value is the type’s zero value. That distinction matters for indexes, counts and cached results. For a set, use map[T]struct{} and test the Boolean result: assign the empty struct when an item is present, and use the Boolean to distinguish membership from absence. Reading a missing key is safe, but assigning to a nil map panics, so initialise a map before writing.
Two Sum stores the index of each earlier value. The lookup happens before insertion, so a value is not paired with itself at the same position. The safeDifference helper also avoids wrapping when a complement cannot be represented by the int type.
GO
Time: O(n). Space: O(n).
When should you use sort.Slice and slices.Sort?
Use slices.Sort when the element type has the standard ordering, such as []int. Use sort.Slice when the elements are records or the comparison is custom. Both sort in place, so say explicitly when the input is being mutated.
Three Sum uses slices.Sort and skips equal values at the outer and inner levels. The sum is formed after converting operands to int64, rather than adding as int and converting afterwards. If a problem’s stated bounds can exceed int64, use checked arithmetic or a big-integer representation instead.
GO
Time: O(n²). Space: O(1) auxiliary space, excluding the returned result.
For interval records, sort.Slice expresses the comparison directly. This version handles an empty outer slice and merges touching intervals as well as overlapping ones.
GO
Time: O(n log n). Space: O(n) for the returned result, apart from the sort’s implementation details.
The code sorts the outer slice but creates new interval pairs in the result. If the caller’s order must be preserved, copy the outer slice before sorting; copying only that outer slice does not clone the inner intervals.
How do slices and append affect backtracking?
A slice contains a pointer, length and capacity. Two slices can therefore share an underlying array. append may reuse that array, allowing one recursive branch to overwrite values another branch can still observe.
The safe rule is to copy a path before storing it in the answer. A path can still be appended and shortened in place while it belongs only to the current recursion chain. If ownership is unclear, make it explicit with slices.Clone or append([]int{}, path...).
Subsets II sorts first and skips an equal value at the same recursion depth. It also copies every completed path, so later backtracking cannot alter a stored answer. The closure captures path and result; declaring the function variable before assigning the function literal lets it call itself.
GO
Time: O(n · 2ⁿ), including the cost of copying returned paths. Space: O(n) auxiliary recursion and path space, excluding the output.
How do comma-ok sets and closures work in DFS?
For a grid, an array coordinate such as [2]int{row, col} is comparable and can be a map key. That gives a readable map[[2]int]struct{} visited set without encoding coordinates into a single integer. Mark a cell before exploring neighbours, then stop at boundaries, water or an already visited position.
This version counts connected land regions and returns zero for an empty grid or an empty first row. It leaves the input unchanged; mutating land to water would save the separate set but would change the caller’s grid.
GO
Time: O(rows × cols). Space: O(rows × cols) for the visited set and worst-case recursion.
How do Go heaps and integer overflow fit together?
Go has no built-in heap type. container/heap works through heap.Interface, whose five methods are Len, Less, Swap, Push and Pop. Push and Pop use any, so type-assert at that boundary and keep the rest of the implementation strongly typed.
For K Closest Points, a max-heap keeps the farthest retained point at the root. When the heap grows beyond the requested size, removing that root leaves the closer points. The squared distance is calculated after converting the coordinates to int64; converting only after multiplying would allow an int overflow first. The same rule applies to products, path costs and accumulated sums.
K Closest Points to Origin on thita
GO
Time: O(n log k). Space: O(k), excluding the returned result.
The example assumes the problem’s coordinate bounds make the converted squared distance representable in int64. If a different problem permits larger values, use checked arithmetic or math/big rather than allowing a silent wrap. For binary search, calculate a midpoint as left + (right-left)/2 when the bounds themselves may be large.
Should a Go string use bytes or runes?
A Go string is immutable UTF-8 data. Indexing it returns a byte, not a complete Unicode character. Use []byte when the problem defines a byte-sized or ASCII-style alphabet and direct indexing is useful. Use []rune when positions must represent Unicode code points. Converting to runes uses additional memory, but it makes the character model explicit.
This longest-substring solution uses runes and stores the latest index for each rune. The comma-ok lookup prevents a missing character from being confused with an earlier index of zero.
Longest Substring Without Repeating Characters on thita
GO
Time: O(n) in the number of runes. Space: O(n).
strings.Builder owns a growing byte buffer and provides WriteString and WriteByte for repeated output. Use len(part) when an encoding needs byte length, because slicing a string uses byte offsets. Do not copy a builder after it has been used.
How should you practise the NeetCode 150 in Go on thita?
Work through one problem at a time in the browser on thita. Select Go, write the solution and run it against the problem’s test cases. Treat a passing run as only part of the exercise: explain the invariant, identify any slice-ownership assumption, and state the complexity without reading it from notes.
Then revisit problems by pattern rather than only by list order. Pair frequency-map work with another counting problem, recursive tree traversal with grid DFS, and a custom heap with another priority-queue problem. The NeetCode 150 by pattern provides the checklist, while the DSA patterns sheet shows the related pattern families.
When the code is comfortable, rehearse in the AI mock interview. It is spoken, runs your code and asks follow-up questions. Practise explaining why a lookup uses comma-ok, why a path is copied before storage, why a heap is ordered as a max-heap, and why a distance uses int64.
Every problem on the list that is live on thita runs in the browser in Go against the problem’s test cases. You can therefore keep the Go representation while testing, then compare another language later if that helps. For a broader revision structure, see the NeetCode 150 study plan.
The aim is not to make each solution clever. It is to make the standard Go choices automatic: comma-ok maps, map[T]struct{} sets, copied slices at ownership boundaries, sort.Slice and slices.Sort, bytes or runes by requirement, builders for repeated output, closures for local DFS, container/heap for priority queues and numeric types chosen before arithmetic. That is how the NeetCode 150 list, practised on thita, becomes Go interview preparation rather than a translation exercise.
Topics
Related on Thita
Your next step
Practise the NeetCode 150 by pattern
Track the NeetCode 150 list on the DSA patterns sheet, run every live problem in 6 languages against real test cases, then rehearse it out loud in an AI mock interview.