Cracking The Whiteboard Interview
In a recent post, I wrote about how whiteboard interviews are an important part of a technical interviewing process and how they play a fundamentally different role than coding interviews. For a company, they can be one of the best ways to evaluate a candidate’s communication skills, their problem-solving ability, and their creativity. For the candidate, they’re a unique place to showcase strengths. They present an opportunity to produce something more meaningful than just a few snippets of code, and to collaborate with their interviewers. Altogether, the whiteboard interview is one of the best places to for a candidate to differentiate themselves from their competition.
To do that effectively, though, candidates need to understand what the whiteboard interview is all about. The interviewers have a structure and a rubric (even if they don’t share it), and doing well in the interview isn’t any harder than getting the interviewers to check each of their boxes.
So: what should the candidate optimize for?
While not a “step” of our process per se, demonstrating strong communication skills throughout the entire interview is the single best way for a candidate to impress. A candidate who fails to arrive at a technical solution but succeeds in engaging their interviewers, sharing their thought process, brainstorming solutions, and conversing about the problem has demonstrated that they are a valuable team member. A candidate who arrives at a solid technical solution but is unable to articulate or analyze it has not.
Unfortunately, shining here doesn’t come naturally to everybody. Many candidates will need to work hard in order to stand out. But working hard pays off: contrary to common belief, communication is a practicable skill, and improving it even incrementally can have drastic effects (even outside of the interviewing context).
Two easy ways to improve your whiteboard communication: first, slow down. Assemble thoughts completely in your head before voicing them. This can be particularly difficult in an interviewing setting where silence often feels uncomfortable, but the important thing to remember is that more often than not, you are the only person perceiving that awkwardness. Second, treat the interview as a conversation, not a presentation. Your interviewers are your future colleagues: show them that you know when to ask for help. Invite them to join you in solving your problems, and express the questions you’re mulling over as you begin to process them. They’ll appreciate the commentary; silent whiteboarders make for boring interviews.
Oftentimes, whiteboard problems are larger, vaguer problems than their coding counterparts. Interviewers are looking to see how candidates handle a tricky situation, and they want to see candidates establish a good understanding of the problem space before diving into a solution. What this means is that as a candidate, you should spend some time trying to understand the problem—even if the solution is obvious. Ask clarifying questions: who will consume this API/interface/method? How frequently will it be called? Is performance an issue? Is memory an issue? Would it make sense to develop a more general solution, or are we reasonably certain this module will only be used for a specific implementation? Do we need to worry about bad input?
This is a good time to try to read your interviewer. Do they find the questions interesting, or are they dismissive? Oftentimes, interviewers will respond to these kinds of questions by asking for your opinion—if that happens, be prepared to give an opinion and to justify it. If you’re not able to formulate an opinion with the information available, feel free to make some assumptions, but write those down on the board to reference later.
2. Breaking Down The Problem.
How a candidate breaks down a problem is perhaps the single most informative part of the entire interview process. Companies are built around complex problems, and the most valuable contributors are the people who excel at dismantling large challenges into smaller ones.
Before starting to break things down, feel free to brainstorm a bit. If it’s appropriate (i.e., the question is something more interesting than “reverse a linked list”), cast a wide net for ways to implement a solution, and then narrow in on the one or two strategies that seem the most promising. There’s no need to jump into a solution immediately, and having a back-up plan can be useful if your first approach eventually proves deficient.
Your goal in this step is to identify what methods you will need to write in order to answer the prompt. How will they invoke one another? Will you need to define any classes or custom data structures? Once you’ve talked through how your program will look, stub out your function signatures on the whiteboard, including their semantically-laden names, arguments, and return types. If necessary, put a comment in describing how your function will work.
Pro-tip: Start from the top-left corner of the whiteboard, and give yourself enough space for each function. Far too often, candidates start writing code in the middle of the whiteboard, causing them to run out of space halfway through the problem.
Doing this step well, before you start writing any code, gets you a lot of points for free. First and foremost, you’ve communicated your intent and shown a proactivity that will set you apart from the majority of other candidates. Moreover, you’ve made the rest of the interview much easier. By writing out function signatures and mapping the flow of your solution, you’ve very quickly validated that your plan is at least feasible. And, if you run out of time at the end of the interview, the interviewers will have an excellent picture of where you were going with your solution, which can turn even a very incomplete solution into a positive one.
Before going on to the next step, take a second to evaluate your design. Do this out-loud, and include your interviewers. If there’s anything glaringly wrong, they may take this time to point out something you may have missed. Even if you don’t understand what they’re saying right away, be sure to carefully consider what they are saying: generally, your interviewers want to see you succeed. Their hints are meant to help you.
3. Identify Edge Cases
This is a quick step, but an important one. At this point, you should have all of the functions and classes you’re going to be implementing stubbed out on the board. Take a moment to consider edge cases, and make a little comment on the relevant functions so that you know to check for them. A few different kinds of edge cases to consider:
- Malformed user input
- Extreme values (i.e., negative values, or above the max range)
- Race conditions (is it possible multiple parts of the system might modify a resource?)
- Side effects
- Undefined globals
Oftentimes, pointing out these edge cases is enough. Simply by recognizing where your solution is vulnerable or brittle shows that you are proactive and conscientious—when you get do get to implementation, you can simply ask your interviewers if it’s okay to code for the general case and assume that edge cases will be handled. After all, this is just an interview, and your code will never be run anywhere other than through the eyes and ears of your interviewers. More often than not, they’ll be happy to let you abstract those implementation details away.
Good news! If you’ve followed steps 1-3 to the letter, this is the easiest part. You know how to code, it’s what you do. You’ve already solved the big problems. You already know your inputs, their types, your data structures. All of the functions you need to implement are small and single-purpose. If you’ve made it this far, you have nothing to worry about.
This step is about filling in the functions you’ve already defined. Many companies are happy to see pseudocode during whiteboard interviews. If that’s an option, take full advantage of it. Either way, don’t get hung up on syntax: remember that whiteboard interviews are primarily about problem-solving, not coding ability.
Do make an effort to write legibly and keep your lines even. Writing on a whiteboard can be surprisingly tricky, but spending just a few extra seconds to keep things neat makes a world of a difference if you need to go back and refactor, or when you’re walking through your solution.
This is a bit different than testing a programmed solution. First, walk through all of your code with a simple test case, making sure that you get the result you’re expecting. If not, go back and fix things until things work as intended.
You only need to do this once. When whiteboarding, it’s usually sufficient to identify what your test cases would be. Frankly, running each of your test cases through your program would be pretty boring, and probably not the best use of your time or the interviewers’. So instead, identify what your test cases would be, call out why they would be good test cases, and have a conversation about test design. No need to write anything down. Just show your interviewers that you understand and appreciate the value of good tests.
Finally, it’s time to evaluate your solution. This is another place where going even just a little above and beyond can make a big difference. Look at your solution and evaluate it from three angles: performance, architectural design, and code cleanliness.
Start with performance. If you can, use Big-O notation to describe the upper bound on runtime. Discuss if any inputs will cause dramatic performance variances. Identify the space complexity. At this point, your code is already written, and you’re probably short on time: don’t go back and change anything unless it’s very easy to do so. Instead, point out where your program is nonperformant and explain what steps you could take to make it stronger.
When evaluating your architectural design, pay special attention to the public interfaces that you’re exposing. Are your methods developer friendly? Do they produce an output that is easy-to-use? Are functions as simple as possible, each with a single purpose and no side effects? Try to make your code compliant with the Principal of Least Privilege: scope methods and variables as narrowly as possible, avoid globals, create closures to contain state.
If you made any assumptions at the very beginning, address those assumptions now. Talk about how they impacted your design, and what changes you would make with a different set of assumptions. By doing this, you demonstrate that you haven’t lost the big-picture view.
Finally, take a look at your code cleanliness. Because your solution may be pseudocode, it’s possible that this isn’t particularly relevant, but take at least a quick scan to ensure that things are looking neat. Add comments to any code that may be confusing.
And that’s it!
Whiteboard interviews can be tough, but none of these steps in themselves are hard. By following these them in order, you remove roadblocks before they become problematic. And even if you do run out of time, this sequence of events guarantees that the interviewers know that you had a plan. Most importantly of all, these steps will empower you to demonstrate every quality the interviewer may be looking for: comprehension, communication, proactivity, problem-solving ability, thoroughness, and organization.
And finally, a parting word of advice: be a human. Relax, smile, and chat up your interviewers. Remember that they’re not looking to hire a software engineer, they’re looking to hire a teammate. And, with a good plan, a good attitude, and just a little good luck, that teammate could be you.