The point of studying model solutions is to learn a collection of patterns. When you encounter a problem that resembles a model solution you already know, you can apply your model solution with a few adjustments, and quickly solve the new problem. You don’t have to start every problem from scratch.

But sometimes a problem isn’t a close match to a model solution, and it also isn’t completely new. It has some characteristics of a model problem that you’re familiar with, but you can’t figure out how to fit the details of the problem into the template you have created for that problem type.

Consider our canonical example, binary search. If a problem provides a sorted list and you need to find a value in that list, it’s clear how to apply the model binary search solution. Pick the middle element, compare it to the target, repeat on either the left or the right half, and so on. But some problems require binary search in multiple sets of data, or binary search on the output rather than the input, or 2D binary search, or binary search inside a dynamic programming algorithm. In these cases, simply applying a model solution template might not be enough.

To deal with these more complex problem types, it helps to learn not just the model solution implementation, but the steps required to find the implementation. This requires learning the solution at a higher level of abstraction. Rather than just looking for a list of sorted elements, look for any data structure with a well-defined “middle” element and a way to calculate whether the target is “lower” or “higher” than the middle. Rather than only applying binary search to input values, consider whether you can use it to find the value to return. Rather than asking binary search to give you the final result, consider whether it can provide an intermediate result as part of another algorithm.

Model solutions are useful because they let you practice a solution implementation. They don’t just explain the solution. They also give you code to solve it. For easy problems, this is often all you need. In the early stages of learning a topic, solving a few easy problems for that topic is a good way to reinforce the ideas in the model solution. But eventually you have to step back and learn the theory of why a solution works. This will help you apply the solution to more difficult problems.

This is a general principle of coding practice. Alternate between theory and implementation. Learn a bit about the theory, then solve a few problems. Then learn some more theory, then solve some more problems. Solving problems ensures that you can apply the theory, and learning theory ensures that you understand what you’re doing and can adapt it to other problems. The LeetCode interface tests you on the implementation and tells you if your code failed any tests cases. But it doesn’t directly test your understanding of the theory. So it’s up to you to write your model solution to be more than just a template for easy problems.

*This year, I’m publishing a series of tips for effective LeetCode practice. To read the tips in order, start with A Project for 2023.*