LeetCode debugging is different from real-world debugging. But as in the real-world, you sometimes have to debug your LeetCode solutions. So it’s worth learning the techniques that work best for LeetCode-style programming.
According to the model solution approach, the goal of LeetCode practice is not just to get your submission accepted, but to learn the right way to solve problems. So the most basic form of debugging is verifying that your solution follows the design that you planned. Even when you are solving a problem for the first time, make a plan before starting implementation. The first step in debugging is comparing your code to that plan. If you’re repeating a problem, then your goal is to implement a particular model solution. Make sure your code matches what you remember about that solution.
Even if you have a model solution implementation that you could compare with your solution, it may still be worth spending time on debugging. One goal of spaced repetition is to figure out which parts of a solution are difficult, so you can focus your efforts on them. As you debug your solution, you’ll naturally find those parts. This may prompt you to re-write them so that they’re easier to understand. Or they may already be well-written, but through the debugging process, you understand and remember them better.
LeetCode problems are well-defined puzzles that are written to be solved using standard algorithms. In theory, you could even prove that your solution is correct using the tools of formal program verification. But even if you don’t go down that rabbit hole, you can check loop invariants to verify that variables have expected values at certain points. If an invariant is violated, that narrows down where in the code you need to look to find your bug.
If you can’t find any bugs but a test case is still failing, it’s not against the rules to use that test case to figure out what’s wrong with your solution. But you don’t have to use the exact test data that LeetCode gives you. LeetCode offers a feature that lets you copy a failed test case into your local test list. Then you can run it as many times as you need to without cluttering your history with failed runs. You can also modify the test case once it’s in your local list. To make it easier to track down bugs, you can make the test case smaller. Maybe your solution only has trouble with part of the test case. Try removing some data to see if you still get a failure. This approach relates to Stack Overflow’s Minimal, Reproducible Example advice. The less data you need to work with, the easier it will be to find the bug.
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.