In late March of this year, the coding interview preparation site LeetCode announced a 30-Day LeetCoding Challenge. Each day during the month of April, they selected one of the coding problems from their archive and challenged developers to solve it within 24 hours. Newly locked-down developers throughout the world took up the challenge, earning LeetCoins and the chance to win LeetCode swag. (Not to mention practicing their coding interview skills).
As one of those suddenly home office-based developers, I thought this sounded like a good daily habit, so I set a reminder to check the site every day for the new problem. By the end of the month, the challenge was popular enough that LeetCode decided to continue it in May, then in June, and so on. Now here we are in December, and it’s still going strong.
As I worked on these daily problems, I took a lot of notes about specific algorithms and techniques, and also about the general process of learning LeetCode problems. I won’t be able to fit everything into this one article, but I’ll summarize some key lessons from my experience this year.
Some Preliminary Claims
Having read a lot of Quora discussions about coding interviews, LeetCode, competitive programming, and similar topics, I know these can be contentious subjects among developers. So let’s get a couple of things out of the way before moving on to the good stuff:
Claim #1: When interviewing for a job, software developers are often required to solve coding problems similar to those found on LeetCode. The interview consists of more than just those kinds of problems, but coding problems can take up a significant fraction of the interview.
Claim #2: Developers at all experience levels often find that their previous experience and education have left them underprepared for LeetCode-style interview questions. Consequently, a site like LeetCode is important for targeted preparation.
Assuming you accept those claims, here’s what I would propose as the ultimate goal of LeetCoding:
The goal of practicing LeetCode problems is to reach a level of proficiency where you can solve a LeetCode-style problem that you haven’t seen before in 20-40 minutes under interview conditions.
Let’s break this down:
LeetCode-style problem: LeetCoding is good for practicing algorithmic programming problems. Other types of interview questions — questions about past projects, Amazon Leadership Principals questions, system design questions — require different types of practice.
That you haven’t seen before: The goal is not to memorize answers with the goal of regurgitating them during an interview. There are too many possible questions, and memorization isn’t a good approach for coding problems. So this study process only succeeds if it helps with new problems. Fortunately, there are a limited number of patterns used by coding interview problems, so even “new” problems will seem familiar after a while because they will remind you of problems you have solved.
20-40 minutes: Coding interviews usually come in two sizes: 1) Short interviews, often used for preliminary screening. Those are on the order of 30 minutes and usually take place online or by phone. 2) Long interviews that last closer to 60 minutes, which are used to make the final hiring decision. During non-pandemic times, these often take place in person. Interview lengths aren’t standardized, and you won’t get the full interview for coding, since the interviewer will use some of it for other questions. Also, sometimes an interview will have two problems, usually an easier one followed by a harder one. So you can’t count on a specific amount of time to solve a problem. But if you can solve easier problems in around 20 minutes and harder problems in around 40 minutes, with medium problems somewhere in between, that should cover most scenarios. One difference in an interview situation as compared to the LeetCode experience is that the interviewer can help get you unstuck or guide you towards a good solution approach. So if you shoot for 20-40 minutes unassisted, that also gives you some buffer when you have a person helping you out.
Interview conditions: This refers to a high-stakes test situation that could mean the difference between employment and unemployment. Also, coding on the whiteboard without autocomplete or Google, and an interviewer who may be reading email during the interview. LeetCode can’t simulate most of these conditions (though LeetCode contests can help produce a feeling of time pressure), so it’s best to do some mock interviewing in addition to problem practice.
How to Reach the Goal
The benefit of maintaining an unbroken streak in the LeetCoding Challenge is that you’re exposed to one new problem every day, and you get to practice solving a problem that you may not know how to approach. Since there’s an active discussion board for every problem, you can always look up information on the solution, whether or not you can solve it on your own. So at a minimum, you get a problem and a solution every day.
But what benefit does this really give you for The Goal? Let’s say you get lucky and, in a day-long series of interviews, every problem you get is one that you recognize from the LeetCoding Challenge. This will probably make you feel well-prepared, at least when you first hear the problem. But how well will it meet the requirements of the goal as stated above? My prediction is that it won’t help much. If you doubt this, you can try your own test: Pick a LeetCode problem that you have already solved but haven’t looked at in a while, and see if you can solve it in the required timeframe. If you can, and you can do this for several problems, then you may be in good shape. If not, another approach is needed.
If you log in to LeetCode, open the user menu at the top right corner of the page, and click on your user name, you’ll get a dashboard of information about your LeetCode usage. One of the sections is Problems Solved, and it includes the total number of problems, how many are in each difficulty level (Easy, Medium, Hard), and your acceptance rate. But one statistic that you won’t see on this page is how many of these previously solved problems you can currently solve quickly. This is a key metric to track for interview preparedness.
Since The Goal is to perform well on new problems, a direct way to approach that goal would be to practice only new problems. That’s the default mode of using LeetCode, and it’s what the LeetCoding Challenge is set up for. Although working on new problems is more effective preparation than not working on any problems, it’s not a great way to prepare for interviews. The drawback of this approach is that it’s too slow. Although every new problem gives you a small benefit, you might need to solve hundreds of problems to become at all competent, and thousands of problems to reach an expert skill level.
Rather than focusing on increasing your total problem count, which just shows how many problems you solved at some point, I recommend instead focusing on how many problems you can currently solve without any help. Here’s a process you can use to do that:
Find a source of new problems. The daily challenge is one source, and it can be a motivating way to solve a new problem every day. But you can also find suggested problems in the LeetCode discussions, or on the Problems tab.
After you solve a new problem, think about whether it’s worth spending more time on (i.e., whether it’s a useful problem). I like to put each problem in one of the following categories:
- Too easy: I can already solve it well enough when I first see it, so it’s not worth spending any more time on.
- Too specialized: It may be a good problem for its own sake, but it’s not applicable to other problems.
- Too similar: I’m already learning a problem like this.
- For future practice: It’s a good quality problem that I want to learn.
- Currently practicing: I’m practicing this problem on a schedule.
- Mastered: I practiced this problem enough that I know it well, so I don’t need to spend any more time on it.
When you start each practice session, select a problem from your currently practicing list. Keep track of when you practice it (date and time), how long it takes you to solve it (minutes and seconds), whether you can solve it on the first try (without repeatedly running and debugging it), and any other notes about how the practice session went.
Based on how well you solved the problem, pick a date to practice it next. When you’re first learning a problem, you might practice it every day, or even multiple times per day. Over time, increase that to every few days, then once per week, then every few weeks. Once you’re doing well with daily practice on Problem A, add a Problem B to the mix, and increase the repetition delay for Problem A. Eventually, you’ll be able to quickly solve problems that you haven’t seen in weeks or months. This process is known as the spaced repetition technique.
You may be suspicious about the process described above because it sounds like an attempt to learn programming through memorization. And there is a risk of using this process to simply memorize code without understanding the underlying concepts. But that’s not an effective way to do well on new problems, which is the ultimate goal. If you just memorize solutions, you probably won’t be able to adapt them when the problem details change.
The purpose of using spaced repetition on LeetCode problems is to learn the limited set of algorithms, data structures, and techniques required for interview problems, and learn to recognize which problems to apply them to. While you shouldn’t memorize code, you do have to learn to quickly implement binary search, BFS, DFS, tree traversal, and the other standard algorithms and data structures. It’s convenient to use LeetCode problems for that purpose because the online judge will tell you if your implementation has bugs, and because it’s better for interview preparation purposes to learn these algorithms in the context of relevant problems.
So those are my recommendations from practicing the 2020 daily challenges. It still takes a lot of practice to reach the point where you can confidently approach most problems that an interviewer throws your way. But if that’s your goal, this process is an efficient way to get there.