We all hate it, but we all have to do it: software engineering interviews. Even the well-prepared candidates inevitably make common non-technical mistakes and are graded harshly for it. To make matters worse, feedback is rarely, if ever, given, and all the while interview preparation has become a standalone business. As someone who has facilitated dozens of these interviews, I believe this current state of affairs is a consequence of candidates rarely being on the other side of the table.
I hate to see good candidates getting rejected due to these common mistakes, so I’ll try to explain how you can avoid them. My main focus will be what your actions mean for the interviewer. I’ll reiterate the important points that have been made on plenty of blog posts already, but I’ll also explain why you should or shouldn’t do those things. More importantly, I’ll provide example feedback, as in what I’d write for an actual candidate, to show how your actions are translated in the feedback.
With that being said, none of these will matter if you can’t solve the problems and/or write code. However, you won’t be seeing any programming questions here. I’ll provide you tips on how to present the solutions, but not the solutions themselves. There are a couple of books I can recommend: The Algorithm Design Manual, Cracking the Coding Interview and Algorithm Design. A quick “programming interview questions” query on your favorite search engine would also give you enough to get started.
You can get an unlucky loop
Everyone talks about this “unlucky loop”, but what does it exactly mean? Here’s my definition: for any candidate, there exists at least a set of interviewers (i.e, a loop) that would result in the candidate failing.
Consider a candidate that has 4-5 years of experience as a data scientist and they apply for an SDE position. Seeing the 4-5 years of experience in the industry, they’re set for an SDE2 loop. SDE2s are expected to have experience in writing production-level code and running it. Can you see the problem? This candidate has obviously been set for failure. The experience they got as a data scientist doesn’t really help a lot for an SDE2 loop. The number of Leetcode problems you solved won’t help (actually might make it worse). They won’t teach you about operational load, cost, metrics, logging and many more really important things. And I promise you it shows throughout the interview. While this is the most common case, there are many others: you might get questions from an area you’re not good at, your interviewer might be having a bad day, your interviewer’s style might not be a match for you… The point is, it happens.
Now you know what a bad loop is and it can happen to anyone. What can you do about it? Not much. You can talk to the hiring manager to understand the job requirements and expectations or solve thousands of programming questions to reduce the chances of getting an unlucky loop. Still, you simply can’t cover all cases. This might sound too cynical, but it’s not. It’s not different from anything else in life. The chances of you getting a bad loop is unlikely, but it’s important to realize when it happens so you don’t get discouraged.
We are here to help you
I can’t tell you how important this is. Try to engage your interviewer. Sure, you’re expected to take the lead, but that doesn’t mean you have to do everything on your own. Ask questions, clarify edge cases, think out loud and state your assumptions. I’m sure you’ve heard all of these before, but I have to reiterate. They’re that important. As an interviewer, the questions I’m trying to answer are clear:
- Is this candidate qualified to perform the job?
- Would I want to work with them?
As an engineer, you’re expected to come up with solutions (1. Is this candidate qualified?). However, what usually follows is that you schedule a meeting and get feedback on it. That’s why when you walk us through your solution before implementing it has important implications. Same thing goes for “thinking out loud”. I won’t hold it against you if you’re thinking quietly, but I’m missing important data. I, for sure, don’t want to work with someone that doesn’t seek feedback from the team (2. Would I want to work with them?). Even if your initial approach was wrong/suboptimal, it’s still a strong positive signal. If the solution required a Hashmap but at first you considered a tree and a list, here’s what my feedback would be: “The candidate considered multiple data structures and eventually settled on Hashmap because of the average O(1) add complexity.” No one is going to write “The candidate considered list and tree data structures first whereas Hashmap was the correct choice.” Trust me, I have seen enough loops. It’s just not going to happen.
Don’t ever start writing code without explaining your solution first
It sounds intuitive, yet a lot of people fall into this trap. Here’s why you absolutely should walkthrough your algorithm before writing a single line of code: it saves you from the “started writing code before explaining their solution” note on your feedback. If you do solve the question correctly and efficiently, it probably won’t matter as much. However, if it was consistent across interviews or if you couldn’t find the optimal solution, it’ll be brought up for a discussion. On the other hand, it can actually help you in numerous ways:
- It’ll help you catch any bugs or missing edge cases. Describing your solution forces you to think!
- If you fail to catch them, there’s a good chance your interviewer will give you hints so you can.
- It gives the interviewer a chance to stop you before you start writing code. Imagine all the time saved if your approach was wrong!
The point is explaining your solution can only do you good. Whether the approach right or wrong is irrelevant.
We’re not code golfing. This gets more important as you interview for a more senior role. We are definitely looking for signals in your code.
- Don’t try to come up with impossible-to-read one-liners. Keeping it simple is your best bet.
- Don’t cut your variable names too short (this might be OK if you ask the interviewer first). If you consistently use “a”, “b”, “foo”; it’ll be noted on your feedback.
- Try to handle the indentation (I know, it’s hard on the whiteboard). We don’t expect it to be perfect, but indent your code and be consistent.
It’s one of those things that sets great candidates apart from the good ones. Having a “Candidate’s code was well-structured and clear. Used meaningful variable names and had a consistent style” on your feedback goes a long way.
It’s not always about the best solution
In an interview, you have around 45 minutes to solve the question and managing the time is an integral part of your interview performance. If you came up with a solution that requires hundreds of line of code that’ll require me to sit there for hours, there’s a good chance that’s not the solution I’m looking for. That would actually be a great time to utilize some of the communication skills I’ve mentioned above. For example, one of the questions I like to ask can be solved efficiently with a customized priority queue implementation. However, it’s really not trivial to implement. And I don’t expect you to. If you can tell me you can do it with O(logN) time with a heap or O(NlogN) time with a Hashmap and sorting, I’ll tell you to just do the latter. It will also look great on the feedback as I will likely write something along the lines of “Correctly identified two different data structures to solve the problem and communicated the trade-offs between them”. Doesn’t that look great? It’s one of the few strong signals that can push “just below the bar” votes to “inclined to hire”.
Find a working solution
Don’t try to outsmart yourself. Just finding a solution puts you in a great position. Here are two example feedbacks I might write for a candidate:
- “The candidate struggled to come up with a solution. They kept trying to find an optimal solution instead of focusing on finding a solution. In the end they confused themselves and despite all my hints, they weren’t able to find a working solution and didn’t produce a single line of code.”
- “The candidate struggled to come up with a solution. They kept trying to find an optimal solution at first, but they eventually scaled back to finding a solution. They correctly identified the brute-force solution and wrote the code for it. Code was clear and they gave the correct runtime and space complexities. They also mentioned the solution wasn’t optimal and gave a couple of ideas to speed it up. Given enough time, they’d probably have a better solution.”
One looks better than the other, doesn’t it? It provides a lot more information that I wouldn’t have without a working solution: coding and complexity analysis. It basically gives me a chance to sell you. Depending on the question, I might vote “not inclined” for both candidates, but I’m a lot more likely to change my vote to “inclined” for the second candidate.
Forget about the bad habits you picked from Leetcode
I’m not saying that you shouldn’t work on Leetcode questions. Because you absolutely have to. However, it forces you to pick up bad habits. This is especially true if you’re participating in the contests. Leetcode is optimized for practicing problem-solving and it does that at a cost. It forces you to focus on one thing and one thing only: find the best solution fast. We’ve already established that it’s not always about the best solution. Keep this in mind during your interview and don’t treat it as a Leetcode exercise. Leetcode doesn’t care about your thinking process, code quality, testing. It only cares about whether your code passes the test cases. This is far from the case for an actual interview. I understand that, especially for new grad roles, solving the question is still the most important thing, but these “small” nuances can set you apart from the rest.
Show us the code
If you’re interviewing for a software engineering position, you have to be able to show us some code during the interview. This is non-negotiable. Not being able to translate ideas into code is a big red flag and if it’s repetitive, you’ll get rejected. There’s no sugarcoating this, so I will reiterate: you have to show us that you can write code. That’s why it’s so important to come up with any solution at all. Without a solution, there’s no code. Without code, there’s no “inclined” vote. Simple as that. No matter how good you’re with communication or at system design, you will ultimately fail the interview.
Don’t speculate about your performance
This one is short and simple: you have absolutely no idea how you did at an interview.
- You solved the question meticulously and wrote the perfect code for it? Great, it was just the warm-up question that most people solve in 10 minutes and you took 45 minutes.
- You struggled to come up with a solution for half an hour and spat out barely working code in 15 minutes? Great, because most people can’t even find a solution (which makes it a bad question, but I digress).
- The interviewer didn’t say anything while you were battling the question and only gave you short “yes/no” answers. Great, the interviewer expects the candidate to do all the work and the less they talk, the better the candidate is doing.
- The interviewer basically solved the question with you, helping you at every step. Great, the interviewer expects the interview to be more collaborative. They hope candidates can reach the solution by following their lead.
See how the same situation can be good or bad based on the interviewer and/or question? That’s why you simply can’t know how well you did. I mean, sure, if you couldn’t solve the FizzBuzz, you can assume you didn’t do great. But without knowing how other candidates do for that specific question with that specific interviewer, you simply cannot know.
Reset after every round
Here’s how we decide if you get the job or not (at least at Amazon and my previous company):
- Every interviewer writes their feedback. At this point no one is allowed to see other interviewers' feedback. We’re not even allowed to talk about it. This rule is followed religiously. We don’t want to be biased when we’re writing our feedback.
- Interviewers submit their feedback to our internal hire website. We can’t see anyone else’s feedback for the candidate until we submit ours. And if we change our feedback after submitting it, it’s marked as such.
- A debrief is scheduled with all interviewers and the recruitment team. The first 10-15 minutes is spent on reading the feedback. This is usually the first time when I, as an interviewer, see how you did on other rounds. After everyone is done reading, BR (the bar raiser. In other companies it’s usually the hiring manager) leads the conversation. We talk about your overall performance and see if there are any red flags and/or consistent gaps. Everyone makes their case for or against the candidate. At the end we have one more vote: anyone is allowed to change their initial incline/not incline vote. And the decision follows.
You have to remember, every interview is completely independent from each other. When I interview you or write my feedback, I have absolutely no idea how you performed on the other ones. Combining this with the fact that you can’t reliably estimate how well you did, you have no reason to carry the baggage on to the next one. Don’t let your perception of how you did on one question snowball into a whole day of suboptimal performance. A single bad performance is not the end of the world.
Don’t give up
Here are two possible feedbacks I can write for a candidate, both “not inclined”:
- “The candidate struggled to come up with a solution. However, they never gave up and they kept at it. They wrote down some skeleton code with their ideas. They were engaged in the question and responsive to my hints. With a little more time, they probably would’ve been able to find a solution.”
- “The candidate struggled to come up with a solution. They didn’t respond to my hints and looked completely defeated. They became flustered and gave up halfway. They didn’t produce a single line of code.”
Now, imagine me reading the feedback from the other interviewers. I see there are three inclined and two not inclined votes. Can you guess for which candidate I’m more likely to change my vote? As tiring as it is, it’s crucial to keep trying. Overall, it leaves a much better impression and changes the tone of my feedback. When I write feedback, I need to document everything. If you give up early, you’re not giving yourself (or me) a chance to show your strengths.
Don’t give up
Yes. Don’t give up. Again. This time I’m talking about the process. Apply again. Interview again. Yes, we all know that the current process sucks. No, it doesn’t test the skills you use everyday. Yes, you’re unlikely to implement that specific thing yourself instead of using the standard library. Yes, I agree that the process is broken and my feelings about it would require another post. I wish we could find a better process that could scale up to the number of candidates FAANG are interviewing, but we don’t simply have it. Not yet, at least. Until then, this is how you get a software engineering job, and complaining, as much as I like to do it myself, doesn’t help you (well, us) land a job. So, embrace it. Don’t forget that rejections aren’t always about you and they don’t necessarily mean you’re unqualified for the job. All you need is a single win and you won’t get it if you don’t try.