How to Pass Technical Interviews
Software engineering interviews are hard. This is true even if you’re an experienced developer and have worked on scaled up production systems.
In my last role, I was an engineer at a successful tech startup. I had a history of impactful projects. And when I left many of my old colleagues had offered to give strong referrals. Based on my resume and list of accomplishments, I could get an interview anywhere I wanted.
But I knew I wasn’t ready. I had switched into this career from a math & stats background. I had never taken an algorithms class or seriously practiced algorithms type questions. The focus of my past work is also primarily on batch jobs and offline processes. Because of this, when I started the search process, my confidence was pretty low.
Luckily for me, the engineering interview process is fairly predictable. Its usually a mix of coding/algos, design, explain your project, and culture rounds, each one driven by a known pool of questions. There’s tons of resources online to help prepare.
I ended up doing 12 onsites from the entire range of company stages, from seed stage startup to large FANG types. This turned out to be way more than ended up being necessary, but this was my first active eng job search. I had no idea how I would perform ahead of time, and I also wanted do more exploration.
I only failed one onsite. The rest of my interviews resulted in turning into offers, pending offers, or going into team matching / role fit after the onsite. All in all, both my phone interview and onsite pass rates were above 90%.
I want to summarize my prep strategy, and offer tips for those that are also starting to look for their next roles.
Data Structures and Algorithms
For the most part, the best way to prepare for these rounds is to go on Leetcode and do enough questions per category until you feel comfortable with each technique. This can take anywhere from 100–300 questions depending on background and readiness.
If you don’t have an algorithms background, I recommend reading and doing every question in this book: http://www.algorist.com/.
In terms of practical tips, I’ll offer them by category of problems:
- Binary Search: internalize binary search, with the technique of looking at the pivot node, then choosing [left, pivot-1], or [pivot+1, right]. A trick with binary search is that it works on more than just a list of numbers. You can use binary search on intervals, rectangles, lists of lists, as long as you map each item in your list to a number to get an ordered list of numbers.
- Heap: Use a heap anytime you want to keep track of a “top” or “min” list of size n. Know how to use a min heap of size n to keep track of a top n set of numbers. Also know why heapify can be done in linear time. Remember that you can store other things besides the sort key in the heap as part of a tuple.
- Iter: Know how to implement an iterator (w/ next, has_next, peek).
- Palindromes, Anagrams, Valid Parentheses: Know how to check if a string holds these properties, and how to extend strings with minimal number of insertions until they hold this property. Do enough questions around these until working in this problem space feels natural, they get asked a lot!
- Intervals: When you approach a problem around intervals in 1d or rectangles in 2d, can you reduce the problem space to one around points, by using left or right bounds, or corners?
- LinkedHashMap: If you’re using Python like me, don’t forget about OrderedDict as a data structure. It can come in useful in situations where you need to group a set of things into an ordered list of keys. LRU / LFU cache problem becomes trivial w/ this data structure.
- MergeSort: Merge sort is incredibly handy anytime you need to combine two hashmaps/lists on disk that can’t fit in memory. Read up on SSTables.
- Graphs/Recursion/Backtracking: I found these types of problems very formulaic. The difficulty is in selecting which algorithm is best (DFS vs BFS), and recognizing that your problem is actually a graph problem. Once you have that, the rest should be trivial.
How many hard difficulty Leetcode questions should you do? I referred to this reddit comment and found it truthful. Choose selectively, do all of the following:
- Median of two sorted arrays
- Alien dictionary
- Deserialize/serialize binary tree
- Merge k sorted lists
- Trapping rain water/skyline problem
- LRU Cache / LFU cache
- Remove invalid parens
- Minimum window substring
- Sudoku solver
- All one data structure
In my own experience, I was asked LFU cache twice, alien dictionary twice, deserialize/serialize binary tree once.
I don’t think it's realistic to expect candidates to solve many hard difficulty problems from scratch in a 45–60 minute session. But some companies do end up filtering for this, so know the common problems ahead of time.
Systems design takes a lot of breadth. It helps to have experience working with live systems.
If you lack systems breadth, read:
- Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems
- Web Scalability for Startup Engineers
Internalize the sections on isolation, replication, and consistency.
If you don’t have methodical design experience, go through https://www.educative.io/collection/5668639101419520/5649050225344512
- The systems design interview goes through a well defined process: requirements, constraints/estimates, high level design, detailed design. DO NOT SKIP A STEP! Forgetting requirements and estimates and moving immediately to laying out a system is almost a guaranteed fail. Resist the urge to just give an architecture you’re familiar with without any digging
- Implement as simple of a solution as possible based on the requirements. Try not to over-engineer
- Practice back of the envelope calculations. A day has rounded 100k seconds. A terabyte is a trillion bytes, a gigabyte is a billion bytes. A cache can store ~20% of requests. Getting accurate constraints will both help guide the design, and impress the interviewer
- If it seems obvious what the design question will be (ie the company’s own product), get estimates for DAU, throughput, storage, read:write ratio before the interview
- Breathe. Slow down
Past Project/Past Work Experience
- Draw out your past projects just like how you would whiteboard an explanation during an interview for practice
- Tailor the response to the time you think the interview wants you to take when answering. If you’re not sure, give a high level overview and then ping the interviewer for what they want next
- Use a context/problem, solution, result/impact/lessons learned structure to the story
- The interviewer is looking for depth. Highlight the end result (business impact), any collaboration, requirements changes, ways you influenced decision making
For Recruiting Teams and Hiring Managers
For the most part, the bar is really high in terms of candidate experience. I did not have a single negative experience during my 12 on-sites. This is with over 60 interactions with engineers, hiring managers, and recruiters.
I didn’t have a single experience where someone was checking their phone passively, or late to the interview by more than a few minutes, or aggressively and obnoxiously grilling me.
Good candidate experience is now table stakes.
The best interview experience I had was at Sift Science, with the hiring manager, where we went through a collaboration designing one of the systems his team supported. What his team covered was highly technical and difficult to explain (part of a large real time ML fraud detection service), but going through the exercise together gave me clarity into the role and I knew I’d have no problems working with this manager.
The best overall process I had was at Dropbox. The questions asked were not formulaic from Leetcode. I was asked questions that took an existing system (like an OS process), and reduced it to a problem using basic algos and data structures. I was also pushed to think through the worst case scenarios in terms of time and space complexity, and change the solution wrt new requirements. Going through these interviews made me a better engineer.
This is actually my favorite type of interview question for coding interviews. In my past job, I asked candidates to implement a basic text based search function. The candidate and I would go through scoring documents based on word counts, to using inverse document frequency. In the process, we’d implement a reverse index, and keep track of top n documents by score. The only data structures needed for this problem were dicts and heaps. I would ask questions based on which areas the candidate had less familiarity with, and ask followups. I would ask the candidate to iterate on their solution and see if it turned into a mess, or be able to handle changes. And the candidate would hopefully leave the interview with more insight into a new problem area, or have a refresher into information retrieval.
I needed four months to prepare for this process, full time. Two months for leetcode and algos, two months for systems design. I am an edge case since I don’t have a traditional background, but frankly I find this odd as I am a tested engineer that has delivered on high impact projects in high pressure settings, and have led small size teams.
I think the expectations on systems design is fair, but most people don’t have two months fulltime to study leetcode style questions.
Can you test for coding ability without turning your interview process into leetcode simulations? I think the answer is obviously yes.
One idea is to consider as an alternative to coding interviews offering candidates a take home exercise path. Not everyone has the time for take homes so this should be optional, but if a candidate is less prepared on the algorithms side, this interview can still test for on the job coding ability. Make the take home exercise fairly involved, maybe up to 10 hours of work. And replace coding interviews during onsites with collaborative follow up feature improvements based on this submitted work.
Another idea is to just offer coding interviews that match on the job projects. Build an API, code the front end, parse a file, find the bug. These can be both challenging and relevant to what candidates will actually do in their future roles.
Engineering interviews can seem daunting. But I think we’re lucky to have such a well defined process. In past job searches I’ve gone through gauntlets for product management and data science. Developer interviews are much more deterministic in terms of results.
But It does require a ton of time for prepare for. We’re expected to show our skills from the ground up every time we do a new job search. There’s much less emphasis on our past accomplishments.
This is reality. One where if you’re not prepared, it can take months of hard work in order to have the ability to switch jobs. This is not a situation you want to find yourself in.
I recommend every software engineer being somewhat interview ready at all times throughout their career and keeping up this specialized set of skills. And if not interview ready, then to take a job that has enough work life balance where they can study on their own to become interview ready, without having to leave and take time off.