Authors: Gayle Laakmann McDowell
Tags: #Business & Economics, #Careers, #Job Hunting, #General
This approach, which I’ve seen far too many times, seems somewhat like throwing Scrabble letters across the room, hoping they’ll spell a word when they land. Sure, it
could
happen—but it still wouldn’t make you a good speller.
Algorithm Questions: Five Ways to Create an Algorithm
There’s no surefire approach to solving a tricky algorithm problem, but the following approaches can be useful. Keep in mind that the more problems you practice, the easier it will be to identify which approach to use.
Also, remember that the five approaches can be “mixed and matched.” That is, once you’ve applied “Simplify and Generalize,” you may want to implement Pattern Matching next.
Approach 1: Examplify
We start with Examplify, since it’s probably the most well-known (though not by name). Examplify simply means to write out specific examples of the problem and see if you can figure out a general rule.
Example:
Given a time, calculate the angle between the hour and minute hands on a clock.
Start with an example like 3:27. We can draw a picture of a clock by selecting where the 3-hour hand is and where the 27-minute hand is. Note that the hour hand moves continuously, not in a discrete jump when the time changes.
By playing around with examples, we can develop a rule:
By simple arithmetic, this reduces to 30 × hours – 5.5 × minutes.
Approach 2: Pattern Matching
Pattern matching means to relate a problem to similar ones, and figure out if you can modify the solution to solve the new problem. This is one reason why practicing lots of problems is important; the more problems you do, the better you get.
Example:
A sorted array has been rotated so that the elements might appear in the order 3 4 5 6 7 1 2. How would you find the minimum element?
This question is most similar to the following two well-known problems:
Finding the minimum element in an unsorted array isn’t a particularly interesting algorithm (you could just iterate through all the elements), nor does it use the information provided (that the array is sorted). It’s unlikely to be useful here.
However, binary search is very applicable. You know that the array is sorted but rotated. So it must proceed in an increasing order, then reset and increase again. The minimum element is the “reset” point.
If you compare the first and middle elements (3 and 6), you know that the range is still increasing. This means that the reset point must be after the 6 (or 3 is the minimum element and the array was never rotated). We can continue to apply the lessons from binary search to pinpoint this reset point, by looking for ranges where LEFT > RIGHT. That is, for a particular point, if LEFT < RIGHT, then the range does not contain the reset. If LEFT > RIGHT, then it does.
Approach 3: Simplify and Generalize
In Simplify and Generalize, we change constraints (data type, size, etc.) to simplify the problem, and then try to solve the simplified problem. Once you have an algorithm for the “simplified” problem, you can generalize the problem back to its original form. Can you apply the new lessons?
Example:
A ransom note can be formed by cutting words out of a magazine to form a new sentence. How would you figure out if a ransom note (string) can be formed from a given magazine (string)?
We can simplify the problem as follows: instead of solving the problem with words, solve it with characters. That is, imagine we are cutting characters out of a magazine to form a ransom note.
We can solve the simplified ransom note problem with characters by simply creating an array and counting the characters. Each spot in the array corresponds to one letter. First, we count the number of times each character in the ransom note appears, and then we go through the magazine to see if we have all of those characters.
When we generalize the algorithm, we do a very similar thing. This time, rather than creating an array with character counts, we create a hash table. Each word maps to the number of times the word appears.
Approach 4: Base Case and Build
Base Case and Build suggests that we solve the algorithm first for a base case (e.g., just one element). Then, try to solve it for elements one and two, assuming that you have the answer for element one. Then, try to solve it for elements one, two, and three, assuming that you have the answer to elements one and two.
You will notice that Base Case and Build algorithms often lead to natural recursive algorithms.
Example:
Design an algorithm to print all permutations of a string. For simplicity, assume all characters are unique.
Consider the following string: abcdefg
This is the first “interesting” case. If we had the answer to P(“ab”), how could we generate P(“abc”)? Well, the additional letter is “c,” so we can just stick c in at every possible point. That is:
We can use a recursive algorithm to solve this problem. First, generate all permutations of a string by “chopping off” the last character and generating all permutations of s[1 . . . n-1]. Then, insert s[n] into every location of the string.
Approach 5: Data Structure Brainstorm
The Data Structure Brainstorm approach admittedly feels somewhat hacky, but it often works. In this approach, we simply run through a list of data structures and try to apply each one. This approach works because many algorithms are quite straightforward once we find the right data structure.
Example:
Numbers are randomly generated and stored into an (expanding) array. How would you keep track of the median?
Data Structure Brainstorm:
Note that the more problems you do, the more developed your instinct on which data structure to apply will be. Hash tables, trees, tries, and heaps are some of the best data structures to solve problems.
Object-Oriented Design
Object-oriented design (OOD) questions come in two flavors: OOD for a piece of software and OOD for a real-world object. Despite the seemingly huge difference between these topics, they’re approached much the same way:
1. What are your goals?
Imagine, for example, you are asked to design the classes for a generic deck of cards. What kind of cards? Are they standard playing cards, UNO cards, or some other kind? Just how “generic” is it supposed to be?
2. What are the core objects?
For example, if you’re doing the OOD for a restaurant, your core objects might be Restaurant, Patron, Party, Host, Server, Busser, Table, and so on. Each of these will become a class.
3. How do the objects relate to each other?
There is probably only one Restaurant, so this can be a singleton class. Restaurant has many Servers, one Host, many Bussers, many Tables, many Parties, and many Patrons. (
Note:
This is just an assumption; talk to your interviewer about this). Each Table has one Server and one Party. Look for and remove redundancies. For example, Restaurant may not need a list of Patrons, since it can get that from the list of Parties.
4. How do the objects interact?
Think about what the major actions that occur in the restaurant are. For example, a Party makes a Reservation with a Host. The Host sits the Party at a Table and assigns them a Server. Each of these actions should generally correspond to one or more methods. By walking through these methods, you may discover that you missed some objects or that your design isn’t quite right. That’s OK—now is a great time to add them!
5. Are there any tricky algorithms?
In some cases, there may be an algorithm that impacts the design. For example, implementing findNextReservation(int partySize) might require some changes to how the reservations are referenced. Discuss these details with your interviewer.
Remember that object-oriented design questions require a lot of communication with your interviewer about how flexible your design should be and how to balance certain trade-offs. There is no “right” answer to an object-oriented design question.
Scalability Questions
When I interviewed at Google, I didn’t know a thing about large systems. Sure, I’d taken a distributed computing course where we studied election algorithms and whatnot, but that had nothing to do with what I was asked. Sort a million numbers? Design a web crawler? Yikes!
I fumbled my way through the problem, and I realized I could do this just fine. Once I forgot that I had no idea what I was doing, I learned that I actually understood the primary complexities of large amounts of data and dealing with multiple systems at once.
All I needed to do was take things step by step. Imagine, for instance, that we’re designing a hypothetical system X for millions of items (users, files, etc.):
1. How would you solve the problem for a small number of items? Develop an algorithm for this case, which is often pretty straightforward.
2. What happens when you try to implement that algorithm with millions of items? It’s likely that you have run out of space on the computer. So, divide up the files across many computers.
3. Now, fix the problems that occur when you are using many computers. Make sure to answer the following questions:
Testing Interviews
Testers have many names: tester, software design engineer in test, software test engineer, quality assurance, and hey-you-over-there-why-doesn’t-this-work. These titles can mean slightly different things depending on the company.
Whatever you call them, testers have a raw deal; not only do they have to master the coding questions, but they also must master testing questions. They must practice coding, algorithms, and data structures on top of the all usual testing problems. If you’re a tester, do yourself a favor and make sure to practice coding—it’s an excellent way to set yourself apart.
True testing questions usually fall into one of three categories:
1. How would you test this real-world object?
2. Explain how you would test this piece of computer software.
3. Test a method (possibly one that you just wrote).
Testing a Real-World Object
What does testing paper clips and pens have to do with testing Office or Gmail? Perhaps not a ton, but your interviewer certainly thinks they do. Your interviewer is using this question to test your ability to deal with ambiguity, to understand your ability to think about the expected and unexpected behavior, and, as always, to test your ability to structure and communicate your thoughts.
Let’s work through this recommended approach for an example problem: test a pen.
1. Ask questions to understand what the object is.
A pen doesn’t seem that ambiguous, but it is. A pen could be anything from a fountain pen, to a child’s marker with multiple colors, to a pen for astronauts. Ask your interviewer questions to resolve this ambiguity. Find out who the users are, and what the pen is being used for.
2. Who is using it, and what are they doing with it?
Small children with poor dexterity are drawing with it, so it probably needs to be nice and thick. They’ll probably be drawing on paper on the floor, but this means that they might end up drawing on the floor a bit.
3. What are the unexpected uses?
Eating it—kids will put anything in their mouths. Drawing on other children or the walls (as my mother once discovered at her friend’s house when she interrupted my sister playing a fun game called “Can I draw a solid line through the entire upstairs?”). Stomping on it. Throwing it.
4. Are there additional stress cases?
Think about hot weather, cold weather, and so on. Not all of these will be applicable in every problem.
5. Can you fail gracefully?
Ideally, we want our pen to never break. But if it does, can we prevent it from exploding?
6. What are the test cases?
At this point, we’ve discovered that we probably want to test for at least the following elements:
a. Nontoxic. Perhaps we discuss the ingredients with poison control, which might be able to offer more specific tests if necessary.
b. Washable. Test drawing on floors, walls, clothing, and skin.
c. Thickness. We’ll probably want to conduct a series of tests to understand what widths are uncomfortable for children, in addition to “live testing” our prototype pen.
d. Softness/Lightness. The material should be a lightweight plastic, so that it doesn’t hurt too much it if hits you.
e. Durability. The pen should not break easily. We should discuss with our interviewer precise measurements about how much pressure it needs to withstand.
f. Leakage. If the pen does break, we want to make sure that the ink doesn’t explode.