“So, how much prep did you do when you interviewed with Google?”
I ask my lunch interviewer sitting across from me. Even though they call this an interview, it’s really informal as nothing during lunch will be submitted as feedback to Google’s Hiring Commitee.
The interviewer gives me the following answer, matter-of-factly.
“I didn’t really prep.”
My eyes open wide and I kind of freeze. I’m thinking “Wtf?”.
The Googler picks up on my surprise and explains as if he had to say this 1000 times before:
“Yeah, it turns out I could do sufficiently well for those technical questions without prepping much.”
Good for him.
Really, good for him.
But that’s not the case for me. And for a lot of other people.
A lot of people, like me, need to practice. We grind questions on Leetcode. We buy the Leetcode Premium subscription. We buy Cracking the Coding Interview, place it beside the bed and rub two fingers on it for good luck before going to bed. We rattle off our Leetcode accomplishments the same way boy scouts blabble about how many cookies they sold. “My stats: 50 easy, 70 medium, 10 hard.”
It’s gotten to a point where some people take it too far.
A friend is preparing for a job interview. You tell him “You should check out Leetcode.”
Another friend fails an interview. “Bro, you’d have made it if you did 20 more mediums.”
Another friend passes an interview. “Good job man! I knew all the Leetcode will pay off in the end!”
Trying to finding a romantic partner. “10 more mediums bro, then you will find it.”.
I don’t understand where it began. Leetcode is this alpha and omega of coding interviews. It starts with Leetcode and ends with Leetcode.
You suck? Do some more. You are good at it? Good, do some more. You don’t want to get rusty, do you?
“Learn how to learn”
During my 2nd year of uni, I read Dr. Barbara Oakley’s A Mind for Numbers. One of the best lessons I took from it was spaced repetition.
Basically, you recall and review what you learned, systematically. The purpose is to keep the lessons fresh in your mind.
This was a game-changer for me.
Back when I didn’t do this, I would grind Leetcode questions to a point where I would forget the questions that I did way back. So, I would go back and review them. But by the time those were reviewed, I realized there were a BUNCH more that I needed to review. And whenever I did a new question that was similar to something I did before, I couldn’t remember the previous question well enough to benefit from the experience.
I was cutting down a tree with a blunt axe, with bad aim, and not stopping for a break. Simply put, I was being inefficient. And I hate being inefficient.
I begin to put down each Leetcode question down into a Google Spreadsheet, as shown below:
Later, I begin to put down some other data, as shown below.
In the beginning, I didn’t really see a big benefit. But as time went on, this changed me from a clueless learner to… still clueless but reliable learner.
Reflections turned out to be the most important column for me in the end. I used this to keep a consistent metric on my performance, based on a Googler’s sample evaluation. I will explain below.
Memorizing answers are a gamble. Sure, it might work, but what are you going to do when you face a question you haven’t seen before?
Try to work on your foundation. Your core problem solving skills. Communication. Debugging. You should be getting better with each question.
When I say “review”, I’m not talking about memorizing answers to any particular questions.
I’m talking about remembering
- the type of question
- how you did well / messed it up
- “intuitive” takeaways from the question.
If there is anything you should takeaway from this post, it’s this.
In the beginning, my reflections didn’t provide much value, as you could have guessed from the screenshot above.
However, my reflections later developed into something like this:
Why did I come up with reflections?
I gained insipiration from a post by a Googler, where he briefly mentions how he evaluates candidates. I will paste it here:
Instead of potential recommendations, I’ll focus on the things I’d like to be able to say. When assessing algorithms and data structures, I want to say something like
- TC (The Candidate) explored the problem and produced a solution that addressed all edge cases, and improved the solution when presented with its shortcomings. In the end, they arrived at an optimal solution.
- TC chose appropriate data structures for the solution, and correctly answered questions about the Big-O of their solution’s runtime and space requirements.
- TC quickly and concisely translated their ideas into code. The code uses standard language constructs and is easy to read. All edge cases are addressed, and TC walked through their code to debug it and verify it’s correct.
- TC drove the problem solving process: they developed most of their own solution, and were able to identify and address shortcomings without my pointing them out. TC required only minimal hints to get them moving in the right direction.
From his points, I summarized the evaluation into the following:
- Exploring various solutions and clearly communicating them.
- Stating the runtime and space complexity (the pros and cons) of each solution.
- Translating ideas into code.
- Debugging your code (visually inspecting your code. Walk through your code with an example, by hand. Edge cases too. This is NOT about running the code in your IDE to check that it works).
With reflections like these, it was super helpful for me to maximize my learnings and lessons with each question that I did. Solving a single question with this approach was equivalent to solving 5 questions the previous way, or maybe more.
This is what worked for me. Find out what works for you.
Here’s the thing. To pass a coding interview, you need to maximize your chances. To do that, you need to work on your weaknesses so they won’t be held liable against you during the interview.
Why? Because a lot of big companies will assume the worse than the better. They would rather have false-negatives than false-positives. You show them a fault, and they will hold that liable. These companies are willing to pass up on a couple of gems than take in a parasite employee.
So, find out how you suck.
Have trouble exploring various solutions? Do more questions. Skim them, don’t code it out. Read, think, then check the answer. Study each answer and understand them thoroughly.
Have trouble translating ideas into code? Write basic data structures and algorithms with pen and paper. Then do questions with pen and paper.
Have trouble with finding bugs in your code? Walk through with an example. Still can’t find it? Try another example, maybe an edge-case.
Have trouble communicating your thoughts clearly? Record yourself. Judge yourself objectively. Take your time and practice. Note what you should do better. Maybe you keep looking up at the ceiling. Maybe you speak too fast. Or too slow. Or not enough. Maybe you say whatever comes to mind because you are pressured to spit out an answer. Be harsh on yourself and ask “would I want to hire this person?”
Have trouble with on-the-spot anxiety? Do mock interviews. Check out Pramp. Get some friends to mock interview you.
At the end of each study session, I would
- review the questions I did for that day
- review a couple of questions that I highlighted for review
- review my Reflections
The beauty of all this? Patterns.
I was starting to see patterns on how I sucked.
There was how I sucked. And there was also my key to improvement.
I frown at my phone. My friend’s profile picture innocently stares back at me on Messenger’s Voice Chat screen. This is the advice I’m getting from a friend who made it to Amazon.
Not quite the advice I was expecting.
Nor is it the first time I heard it. Back when I was beginning my journey, this sounded like a terrible idea.
You don’t learn much. You are basically memorizing solutions.
But looking back, there are legitimate reasons on why you would do this.
Remember my 4-point summary of my evaluation? If you are good at the latter two:
- Translating ideas into code
- Debugging your code
Then you can spend your time more effectively by focusing on the first two:
- Exploring various solutions and clearly communicating them.
- Stating the pros and cons of each solution.
I tried it.
When I got to this point, I would just -
- Read the question
- Think about various methods to solve it in my head
- Check if it covers edge cases
- Compare runtime and space trade-offs
- Check the solution
I did a handful of questions this way, and they were a super good use of my time.
“Dan, where’s the part about studying algorithms? Why aren’t you recommending the book Introduction to Algorithms by Thomas Cormen? How could you write a post about Leetcode and not mention the word ‘sort’, or even Dijkstra? To get better at Leetcode you need to study algorithms and build a strong foundation!”
I’m not writing about how to get better at Leetcode.
I’m writing about how to get better at technical interviews.
Little ironic, but they are completely different.
If companies were hiring candidates solely based on Leetcode performance, the algorithm dogs from Asia will take over the market.
But companies aren’t trying to hire the best algo-experts. They are trying to hire the best employee. A team player. A communicator. A thinker. Problem solver. Someone that can take constructive criticism. All of these things.
I’m not denying that you shouldn’t study algorithms, nor that you shouldn’t read that book. It’s a great book. I had to cover that book in one of my courses at university. I do recommend it. If I had a physical copy, I would place it beside my bed and rub my fingers on it for good luck.
But technical interviews are much more than just writing the correct code on a whiteboard. It’s everything in-between. There are a lot of subtle traits that are judged during the entire problem solving process.
Is this person good at thinking through a problem?
Can they communicate well?
How do they respond to feedback?
How do they find errors in their solutions?
How do they respond to hard problems?
It’s a big topic. I’m no master at it. And I’m not even gonna try to address all those topics in this post.
But let’s take it step-by-step. Leetcode is a huge part of our interview prep. And like cutting down a tree, there are more effective ways to do it.
That’s all. Hope it helps. Happy interviewing!