In case you weren’t already aware, the market right now for software engineers is super hot - it’s crazy out there. A combination of the entire world moving online, people burning out of their jobs and a chronic shortage of experienced software engineers means there’s never been a better time to see what’s on offer. If you want fully remote, better pay and a title change, there are many companies out there willing to give it to you.
What’s even better is interviews are remote now, which tips the balance in your favour. They’re easy to schedule and far less pressure than writing on a whiteboard in-person (although designing a system in a Google Doc is a bit unnatural feeling).
The downside of job-hopping of course is preparing for the dreaded Data Structures & Algorithms interview process. I won’t debate the merits (or lack thereof) to this process; plenty of people have talked about this before with much more eloquence and many more data points.
Instead, I want to share some things that worked for me over this summer while I was interviewing. In the aftermath of leaving Cuvva, I’ve given a tonne of informal advice to people who’ve slid into my DMs or reached out about making moves, and this post is intended to serve as a way for me to stop repeating myself - although I am always happy to help and answer questions.
Particularly in the mobile space I find that people aren’t really aware of what’s involved in these types of interviews or don’t really expect them, so hopefully the information here can serve to forearm and forewarn people.
How to Study
It’s tempting to simply login to Leetcode and do questions at random, looking up the answers when you get stuck - but you’ll find this isn’t a very effective way to get information into your brain. I highly recommend actively studying computer science basics to brush up on your core knowledge, as well as common algorithms, data structures and strategies.
When I say “actively studying”, the process for me looked like this:
- Spend an hour or so reading about the topic at hand - whether that’s recursion, Djikstra, bitwise operations or whatever other horrible thing I wanted to learn that day.
- Take hand-written notes. Studies have shown that writing out notes by hand is far more effective in terms of retention.
- Leave that concept for a day. Feel free to study something else in the meantime, but let that topic end up in the diffuse part of your brain while you do something else.
- The next day, type these notes up into a knowledge base-type program.
- Revisit these notes a week or so later - if the topic is, for instance, the implementation of a HashMap - practise the implementation again.
As you can see, my strategy involves repeatedly accessing/reviewing the same information several times. This is a form of spaced repetition, and it’s one of the most effective ways of getting information to stick. Reading information once is not enough.
I also recommend using this technique when tackling coding challenges. For instance, you might initially struggle with doing questions which involve depth-first search. It’s fine at this point to look at the answers, but then revisit the same question a few days later and try to recall the technique. A few more days later, attempt similar questions which use variations of the technique. This should help the information “click” in your brain, and you’ll find you end up rather good at it after a bit of deliberate practise.
Earlier I mentioned using a knowledge base-type program - these allow you to make notes into a personal wiki of sorts which shows the interconnection between concepts. I highly recommend Obsidian, which uses markdown files, supports LaTeX formatting, mermaid.js-style graphs and is hugely extensible, with a large list of community plugins. For those curious, I’ve open sourced my notes from my studies here - it’s by no means perfect but it gives you an idea of how Obsidian works and how to build a knowledge base.
I like this tool so much that I’ve incorporated it into my day-to-day as a place to just offload information for later retrieval. A second brain, indeed. There are plenty of other alternatives of course if Obsidian doesn’t gel with you for whatever reason - a wiki on GitHub might be enough for you.
I also used an iPad Air with Notability and an Apple Pencil for sketching out concepts when markdown wasn’t very effective, although I ended up not using this as much as I thought I would - pen and paper worked better for me.
It’s also worth mentioning that for writing out coding portions, don’t use an IDE. Autocomplete gives you a false sense of security and you won’t have it in an interview - I practised recalling algorithms and data structures in Sublime Text.
One of the worst things about Leetcode is it can pretty easily make you feel really stupid, especially if you just dive in, and this sucks all of the motivation out of you. Two things:
- It is meant to be hard, and expect some discomfort. You’re going to struggle at times and you have to push through this feeling. I promise you it gets better.
- It is far easier and more pleasant to ramp up slowly if you have the time. Do this via warmup questions.
“Warmup questions” are super-easy ones that get you into the swing of things and reward you with success. What I found the most useful was going to Leetcode’s “all problems” set and sorting by “most accepted” (NOT “difficulty”) and starting from there. This really helps boost your confidence and makes you feel like you can start to tackle the harder stuff and I highly recommend it.
I also strongly advise you to do these gentle warmup questions on the morning of any coding interview. Like warming up before physical activity, these will get your brain into problem-solving mode without leading you into a pit of despair because you chose to start your interview day with a hardcore dynamic programming problem.
What to Study
Narrowing It Down
The surface area of “all computer science” is rather large - I highly recommend narrowing the scope of your learning as much as you can. There’s a couple of examples of this:
- At Company X, I know that they don’t ask Dynamic Programming questions anymore, so I’ll skip learning DP and focus on other stuff.
- DP questions are rare enough (and hard enough even with extensive practise) that I’m willing to take the chance and bet that I won’t be asked a DP question. That way I can focus on other things and maximise my chances.
For either approach, spend as much time as you can on the Leetcode forums or Blind (as bad as the site is…) and try to work out what you’re likely to be asked, as well as unlikely to be asked, based on your target company/companies. Then optimise your studies appropriately. This is a risky gamble in some ways, but for me the benefit of narrowing my studies was enormous as it let me really focus on more relevant stuff.
The other thing you can do is search for Leetcode questions by company, and then rank by frequency. This will also give you a general idea of where to focus and what to avoid. Note that this is meant to give you an idea of topics, not find you questions that you can memorise - this is a fool’s errand. By the time questions are on Leetcode, companies tend to have retired them.
Knowing your data structures inside out is table-stakes, and before you do anything else, I’d recommend that you make sure you know the most common ones like the back of your hand. This includes their space/time complexity for insert/delete/lookup - you will be asked this - and their implementation. Make sure you can build a simple Map, Trie, Linked List etc and do common manipulations on them. It’s amazing how many interview questions are solved with simply inserting the appropriate data structure in the right place.
Learn the Patterns
Another high-value strategy I found was learning the common patterns found in many interview questions and when to apply them. This article does a great job of summarising most of them with examples of Leetcode questions utilising these strategies. If you practise all of these, you’ll do well - the majority of the struggle with coding questions is working out the approach, and having a heuristic for this helps immensely. See my notes on this here.
The Blind 75
In a similar vein, the absolute best bang-for-your-buck is working through the so-called Blind 75. This is a list of questions that covers all of the programming techniques and algorithms that you’re likely to see in an interview. If you’re pressed for time and only have a couple of weeks to study - these are the questions you want to do over and over to internalise them. Again, narrow these down further if you can.
You might be a mobile engineer but you’ll still get asked system design-type questions. What exactly you’ll get asked is an open question though, and this varies not only from company to company but also between teams. At FAANGs, you’re more likely to be asked to design a distributed system than a mobile client, and if you’re like me you have very little experience in that area - so focus on that as you can likely get by in design mobile architecture without studying (although still study it if you have time!).
That said it’s a continuum, and you might be asked to design a distributed system, a mobile client, or the intersection of both at the same time - what does the API look like in that case, and what tradeoffs do design decisions on the backend cause on the frontend?
Or more likely they won’t specify, and it’ll be up to you to ask exactly what the interviewer means when they ask “design Instagram”. If I could give only one piece of advice for system design interviews, it’s “ask questions”.
Signals are what your interviewers are looking for, and they indicate your level of seniority. If you’re aiming for a higher salary, you’ll want to give signals that you can think about the bigger picture - where the code you’re writing would fit into a broader system. Being able to discuss tradeoffs is also a very good indicator - did you choose slower writes over faster reads? Why did you optimise for that? How does that make sense within a distributed system?
In general, the system design interview is where you think about these kinds of problems and where the big money is made, but if you can discuss these things during the coding portion of the interview too, that’s even better.
The other signal that companies are keen on is leadership skills - have you lead a project or team to success? If you lead them to failure (it happens!), what did you learn in the process? Showing decision making that benefitted the company is great; so is showing mentorship skills, personal growth and empathy for your colleagues.
You’ll generally do this in the behavioural part of the interview, and many people under-prepare for this. It’s worth spending a chunk of time looking over everything that you’ve achieved at every role, everything you’ve failed at, and working out what you’ve learned from the experience. Write it all down, really reflect on it and internalise it. I found doing this really quite interesting and I’ll take insights that I learned about myself from this process to other jobs.
Ultimately, what I’m trying to say here is that some parts of the interview process are more important than others - depending on what you’re optimising for. The coding portion should be seen as fairly binary - you’ll need to pass it to get an offer. But system design and the behavioural parts are where you tend to get either up-levelled (yay!) or down-levelled (boo!), and many people neglect them.
- You cannot vocalise your thoughts enough. Explain every thought out loud. It’s not very natural, but your interviewer wants to know where your mind is at. Despite how weird it feels, you can totally practise this at home. Do at least a handful of questions, talking to yourself the same way you would with an interviewer present - this will make it feel more natural when the time comes.
- Use empty functions and back-fill later. It’s easy to get stuck on a small implementation detail - but you’re allowed to get a bit hand-wavey at times. For instance, you might want to call a function that does something fiddly with some values as a subroutine in a more complex algorithm; give it an appropriate name, leave it blank and move on with the overall implementation of the solution. If you’re lucky, your brain will have worked out the implementation in the background whilst you’ve done other things, and you can go back and implement it at the end. If you’re really lucky, the interviewer might not care about this tiny implementation detail and you won’t have to do it.
- Do your research on the company. Read their tech blogs and ask questions that make it clear that you understand some of the problems they’ve solved at-scale. This gives you serious brownie points, but also you should do it anyway because you’re interested in what they do.
- Write down lots of notes during the system design interview. Write a checklist of things you know you want to tackle but haven’t done yet, and write it on the document the interviewer can see. This way they know you’re thinking about all the aspects, even if you run out of time at the end. This list might include:
- etc etc.
- When you test your coding solution, step through and actually write the value of each variable in a comment at each step. It’s far easier for the interviewer to follow, and means less for you to hold in your brain and get muddled over. You will spot mistakes during this step - that’s what testing is for! But don’t stress. Better to find it and correct it than not notice.
Leetcode is a given. Sorry, there’s no getting away from it. A subscription is cheap, worth it, and has no commitment period. As already mentioned, the Blind 75 is probably the most useful resource you’ll want to take away from this post, especially if you’re time-limited.
If you need a little more structure and explanations, I found Algoexpert to be a gentle ramp-up with good quality explanations in video format, if that’s your preferred way of absorbing information. However I do not recommend their system design offering - it’s not great.
Cracking the Coding Interview is a classic for a reason. It’s a huge, doorstop of a book but most of it is answers to questions, so don’t be too intimidated. It also has a lot of discussion about the interview process in the first chapters which were useful.
Lastly I really liked Grokking Algorithms, which serves as a gentle introduction to many of the algorithms that you might need during an interview. It’s a great book and probably gentle enough a read for people who aren’t in computer science. If you finish that and want something a bit more hardcore, The Algorithm Design Manual is pretty great, and it’s worth keeping on your shelf anyway for reference.
For examples of distributed systems and common questions like “design WhatsApp”, I found the course on Grokking The System Design Interview to be well-worth it. The answers aren’t incredibly in-depth but that doesn’t matter too much - it gives you a broad idea of how to answer these types of questions. If you’re a mobile engineer and haven’t done anything like this before, it’s a very useful resource.
Some companies will ask you system design questions which are mobile-focused, and for that I found this framework impossibly useful. Whilst us mobile engineers do system design all the time, how to answer these questions was a bit of a mystery and there’s very little information out there - except for this excellent repo.
In terms of books, Designing Data Intensive Applications is the classic here for a reason, and not too difficult a read. For those looking for a gentler ramp-up, Understanding Distributed Systems was also a lovely read that I enjoyed.
If you have the time, running through practise interviews can also be exceptionally useful, if only to get you used to the time pressures and how to constantly communicate your thought process throughout. Pramp is the most commonly used one, as well as Interviewing.io. At the very least, get a friend to mock interview you and give you feedback at the end.
I have to admit that I didn’t do this - I don’t recommend your first big-tech interview experience being a FAANG.
With all the preparation in the world, one thing you can’t account for is luck. Steve Yegge talks about the anti-loop in this excellent article and it’s worth a read, but essentially be aware that you might not get the company you want, or it might take a couple of stabs at the process to get it. These sorts of interview processes optimise for avoiding false-positives, which means they get lots and lots of false-negatives. Don’t feel too bad if it happens - although I know that it sucks.
With that in mind - best of luck. Do prepare as much as you can. Don’t let the company rush you - you’re in the position of power here. When you get that offer - negotiate. And don’t forget to reverse-interview them so that you make sure that the move is right for you: don’t just chase higher TC numbers.
Go get that dream job you’ve always wanted.
If there’s anything else that’s worked for you, feel free to share, and do reach out to me if you want any more advice. Thanks for reading, and a big thanks to Luca Nicoletti for giving this article a once-over.