Want to crush your coding interviews? There's one tool that separates the amateurs from the pros: LeetCode.
But here's the thing: Most people use it wrong. They mindlessly grind through problems, hoping quantity will somehow translate to quality (Spoiler alert: It won't). The secret? Learning how to learn.
I show you how to optimize your preparation process and skyrocket your interviewing skills. Ready to transform your coding game?
As real as it gets
This is how you are going to be evaluated so better to be comfortable in that same kind of environment.
LeetCode provides a plain text environment with no autocompletion (only syntax highlighting). My first time using the platform I couldn’t even write a simple for-loop in Java. Typing even the most simple syntax without autocompletion felt so unnatural. No secrets here, you need to get used to it.
Your brain is so used to using the IDE features that you don’t even know you are using them until you don’t have them anymore. Using breakpoints? Forget about it, here we think hard and use strategic prints to understand what’s going on.
You will have to know the APIs available in your language of choice. I became genuinely comfortable using things I had never used at my job like Arrays.deepToString or doing bit-shifting operations.
Your interviewer doesn’t expect you to know everything by heart.
Everybody allowed me to Google something if needed. Knowing APIs by heart allows you to think much faster as you don’t need to worry about details such as how to print an int[][]
or the syntax for defining a custom Comparator
.
You have larger problems to solve during the interview than fighting against the language you have chosen. Showing proficiency there definitely helps. Maybe it doesn’t impress your interviewer that you know your language inside out but it projects a poor image of yourself if you have to Google the basics.
Mock assessments
It’s a premium feature but one that makes going premium definitely worth it.
With this interviewing mode, you get a configurable amount of random exercises to solve in a fixed amount of time. You also have the opportunity of choosing a particular company so problems are taken from that company’s pool reported by other LeetCode users.
Once you click the start button, there is no coming back. No pause, no bathroom break, no choosing the category or difficulty of the problems. Exactly as a real interview would be.
You want to expose yourself to thinking under pressure as much as possible. You can be a genius who designs elegant solutions but if you can’t do that in 30 minutes then you will fail the interview.
Once you’ve finished, you will receive a performance report comparing you against other candidates.
It also shows you an overview of your performance across different areas and a nudge about where you should be focusing on.
Don’t be too distracted by those scores if you are using LeetCode (and most people are) as preparation for interviewing. The score is derived from the time complexity and memory usage of your solution. However, it will never take readability into account.
Sometimes the most efficient solution is the hardest to read, understand, extend or debug. You are being judged on those topics as well even if they are not mentioned in the report. That doesn’t mean interviewers will be satisfied with a readable brute-force solution but you get the point.
Think and only then act
Impulse control is everything.
When you have been coding non-stop for 15 minutes and feel that you’ve finished your algorithm, the immediate urge is to hit the RUN button and hope to see that magic text saying SUCCESS. Don’t.
Once you’ve finished your coding you need to review the changes. Then review them again.
If you click RUN and get a disappointing FAILURE result, you will feel the natural urge of immediately fix the obvious (best case scenario) bug and submit again as fast as possible. It’s the way our brains are wired, the dopamine rush we get when we triumph at any task.
You will regularly find that many other bugs were hiding in your code waiting for their chance to sucker-punch you.
Take your time to analyze the problem and understand what happened. Not only the line that failed but the entire code again. If you missed one tiny thing, how can you be sure you haven’t missed many others?
Your interviewers are judging what kind of programmer you are:
Are you someone who stops to think if there is more than meets the eye? Someone who carefully checks the code to understand what went wrong.
Are you a hack-and-slash programmer? Someone who tries to duck tape the error by adding yet another if statement, submitting without thinking and praying that this time all the test cases are 💚.
This is also valuable advice for your career. Every time I have to send a pull request, I look at the same piece of code three different times using three different diff tools. More often than I would like to admit, I end up finding something I’ve missed in the previous self-review round.
If you don’t restrain that urge to click SUBMIT and call it for the day, you are abusing your reviewer’s time. They will have to flag all the issues that you could have fixed on your own if you had been a little bit more careful with your work.
Free vs Premium
I started with a free subscription and I think everybody should do the same.
It is more than enough to get you started. One can only take true advantage of the premium features once you’ve solved a large amount of the basic problems offered by the platform. I’m sorry but money can’t accelerate your learning at the beginning.
After one month of using it 2 hours a day Monday to Sunday, I finally decided to invest 35 USD (~30 euros) to get the best out of my time. I reasoned the cost was 1 euro per day which is close to nothing as I only planned to use it until I landed the job of my dreams.
My focus was on finding the best opportunity for my career, so I had to become a master of my craft. LeetCode’s free version was a powerful ally on that journey. If Premium features improved my preparation even slightly then it was already a worthy investment.
Premium gives you access to features like (sorted by importance for me):
Premium questions
Select questions by company
Sorting questions by frequency
Autocompletion
No waiting time between submissions
Official solutions
Explore cards
Is it necessary? I guess not. Does it help a lot? Hell yeah!
It’s the investment with the highest return you can make. $35 might be negligible or not depending on where you live. If Premium helps you to land a bigger offer, then it will pay itself.
The discussion section is the gold mine
Enter the discussion forum. Always.
After you are done with a problem, regardless of solving it through a terrible brute-force solution or not solving it at all, you have to check the comments.
In the discussion forum, you will find at least three completely different ways of solving the problem. Different solutions, and different trade-offs in terms of time and space complexity.
Probably the most performant solution is an already existing algorithm or obscure technique that no one can realistically ideate during an interview unless they’ve seen it beforehand. That’s fine as no one expects you to come up with such during an interview anyway.
Reading and thinking about those solutions will expand your horizon about how problems can be solved. Those ideas can be leveraged in other problems because at some point all problems start to look similar to one you’ve previously solved.
Don’t lurk, contribute
I contributed to the discussion section as much as I could.
Replying to questions, upvoting the best solutions, and even posting my own. Sometimes the core logic of my code was the same as another solution but I considered posting like submitting a pull-request at work.
It helped me to double-check my work and add comments to the non-straightforward parts of the code. Also forced me to write a brief explanation of how the algorithm works in plain English.
I use the Feynmann technique for diving deep into my understanding of the solution. Sometimes I feel that I finally understood something and still, I felt incapable of explaining it clearly. That’s a reality check where I come clean with myself about how much of the topic do I comprehend.
Now that you think you understand a topic reasonably well, explain it to a 12-year-old.
– The Feynman Technique.
LeetCode templates
There are thousands of different problems but only a handful of patterns.
The more problems you face, the more you start observing the hidden patterns that connect all of them underneath. Sometimes the pattern is hidden and it’s up to you to uncover it.
If you think about cities being connected by routes then it’s intuitive to think about a graph where cities are nodes and routes are edges connecting nodes. Other times the representation of the solution space is not that obvious.
In a finite state machine, a given state is a node in a graph, and moving towards different solutions is just exploring the graph. All kinds of graph transversal algorithms can be used then.
Remembering tricks leads you nowhere
Solving as many problems as possible and hoping to face a known problem during the interview is a terrible strategy.
There are so many different problems with so many different variations that even if you are lucky enough to face a problem you have already seen, chances are that you won’t remember the “trick” to solve it.
Your memory is only useful for remembering the patterns, not the individual problems. When the time comes, you are barely going to remember the solution. Or even worse, you will remember only half of it and are going to spend your energy trying to recall the missing details from your memory as you go. You will end up at a dead-end.
When I say patterns I’m not talking about the problem’s categories. The following aren’t patterns:
Graphs transversals
Dynamic programming
Tree transversals
Linked lists
Those are more like the general topics for the questions. The patterns are the techniques used for the solutions such as:
Using a sliding window on an array (or a String, which is just an array of characters).
Using fast and slow pointers on a linked structure.
Using multiple data structures combined.
Once you understand the patterns you have a powerful tool in your belt for solving any problem similar to that one. Which is much more useful than just hard-coding a trick that won’t last long in your memory.
TODO-REDO-DONE
One day, I had the idea of re-doing an exercise I had previously solved.
What a waste of time don’t you think? If I solved the problem in the past, I should be able to do that again. This time much quicker than before, as I was already familiar with both the problem and the solution.
Imagine my disappointment when I couldn’t figure it out. Ok, maybe it was just bad luck I thought. Let me try another one… same happened. Was I getting dumber?
Something had to change given that my approach wasn’t working as I planned. I started analyzing my process for dealing with hard LeetCode problems. Some problems are just really complicated and it’s fine to check for the answer if you are not able to come up with an answer in a reasonable time frame.
No one has enough time to spend a week on one single problem which solution might be an obscure algorithm. One of those that you either know of it or not. Only geniuses can come up with those algorithms (and probably not during an interview) and I’m not one of them.
Checking the solution right away is never the answer.
You need to think hard for at least an hour or so. Hence, when you read and try to understand the solution (sometimes just understanding the solution can take an hour on itself) it’s more likely to stick in your brain.
For the problems you think you understand, you must revisit them in the future to double-check if you accurately understood them or not.
There are known knowns. These are things we know that we know. There are known unknowns. That is to say, there are things that we know we don’t know. But there are also unknown unknowns. There are things we don’t know we don’t know.
– Donald Rumsfeld
This is the method I developed for fighting against the unknown unknowns. I call it TODO-REDO-DONE.
The first time you see a problem it belongs to your TODO list.
If you solve it without breaking too much sweat then you can mark it as DONE.
What if this problem was a tough nut to crack? Let’s move it to the REDO list and give it another look after a few days.
What I cannot create, I do not understand.
– Richard Feynmann
You will be exposed to fewer problems but the ones you have practiced you can be sure you understand them inside out. Less is more here.
Luckily LeetCode allows you to create your lists of problems so you can use that to keep track of which state any problem currently belongs to.
Walk before you can run
LeetCode’s problems are classified into three levels of difficulty:
EasyPuzzlingMediumMind-bendingHardImpossible
Easy problems will feel challenging. Don’t be disappointed if you need an hour (or more) to solve only one.
Your solution is going to be very crappy and inefficient but that’s perfectly fine as you are going to check in the discussion forum why the performance of your idea is so bad.
Maybe your algorithm has the perfect time complexity and an implementation detail is trashing the performance at runtime (like for example concatenating lots of Strings in Java). No problem at all, now you know. Next time you won’t repeat the same mistake.
Start with Easy and move to Medium when Easy problems start looking doable at first sight.
Why start by tackling Easy problems? Binary search ain’t a secret to nobody.
Can you code it in 2 minutes without hesitation?
Can you do it with enough confidence that you are not introducing any bugs?
That’s the level you need to achieve to succeed.
A binary search is only a tool you need to solve a bigger nastier problem. Same for BFS and DFS. Know them by heart, so when the time comes you are not spending brainpower on the basic building blocks but the big picture.
Beware of misclassification. Some Easy problems should be Medium and some Medium should be Hard. Don’t be surprised if you find an Easy problem that’s super tough to crack.
About Hard problems
I haven’t faced any interviews.
Those problems are certainly very hard. They are challenging even while practicing at home without pressure.
Solve the most famous ones like N-Queens or Merge k sorted lists but don’t obsess with them. You might think that you are not ready for interviewing because you don’t know how to solve one particular problem that Google uses in its process.
If you have reached that point, then chances are that you are going to be just fine.
Practice every single day
Don’t have time to do a full exercise? Do a 15-minute session. Once you read the description you will keep thinking about it in background mode.
The first few days are the hardest but it gets much easier with time. You will be surprised when you even start enjoying solving coding challenges. I’m not joking, it will happen to you if you practice enough. It becomes a tiny part of your life at least for a few months.
Think about it as a game.
Some people solve candy crush levels, you do LeetCode challenges.
It’s not that different except that in the end, you get the job of your dreams as a reward for playing.
Hungry for more?
This is a list of the most useful LeetCode challenges.
Also, some YouTube channels worth checking: