Some job interviewers ask you to describe your career history in great detail. Some want you to to explain the most obscure facets of the language you'll be working with. And some will give you a puzzle and ask you to design a program that solves it.
This last category is by far my favorite sort of opportunity in an interview. I'm a programmer because I love solving puzzles, so showing off that love is far more likely to make me look good than struggling under pressure to remember whether it's ArrayList or Vector that is thread-safe. (Tip: It's Vector.)
I immediately jumped to the most obvious solution -- not because I expected it to be right, but because I wanted to find some answer quickly and then improve it. I said:
When you get asked a puzzle problem, remember above all else that the interviewer is much more keen to know how you think than whether you get the "right" answer. There may be some specific technique that they are hoping you know. But even if the answer is not immediately obvious, don't panic. If you sit there and explain your reasoning, refining your technique out loud, you can make up a lot of ground by showing that you can think on your feet.
A good example is the question I got from the Director of Engineering at Digital Motorworks. Not only did I get the job, but that portion of the interview went so smoothly that I wrote down the question, my answer, and his reaction to save for posterity. Here is a recap of the problem:
You're responsible for implementing a method called "sumExists." This method should read two arguments: an integer, and an array of integers. The return value will be a boolean, which is true if and only if there exists some combination of two distinct elements in the array that sum to the original integer.
For instance, suppose you call the method in this way:
sumExists(5, [7, 1, 2, 6, 4])
The array contains the elements 1 and 4, and 1+4 = 5, so the method should return true.
I immediately jumped to the most obvious solution -- not because I expected it to be right, but because I wanted to find some answer quickly and then improve it. I said:
"If you wanted to use brute force, you could just inspect every element of the array, and compare it to every other element of the array, and see if they sum to the first number. But that would require you to perform O(n2) operations, which is dumb. So I would like to find a better solution.
"Suppose that we sort the array. That would take O(n*log n) time (QuickSort, remember?) to complete. Where does that get us? Well, then we could quickly find the largest number and the smallest number of the array and compare them to each other. We'll put counters on the left and right ends of the array, and add those values. If they add up to the target, then we're done. (Note: in the example, the sorted array is [1, 2, 4, 6, 7]. The high and low numbers are 1 and 7, which add up to 8. Too high.)
"If the resulting number is too high, then the biggest number must be too big. So we'll move the right hand counter to the left and try adding a smaller number to the smallest. On the other hand, if the sum is too low, then the smallest number must be too small. So we'll move the left hand counter to the right and try again.
"By doing this we'll be able to test pairs of high and low numbers until either we find the sum we need, or the counters meet in the middle. If the sum is correct then we return true. Otherwise, return false.
"Scanning the list in this way requires only one pass, which takes O(n) time. But the sort was already longer, it takes O(n*log n) time. The time to scan a large array once would be much smaller than the time to sort, so we ignore that factor. This solution takes O(n*log n) time."
As I said, I wrote down the response and saved it. So this is more or less a direct quote: "I've been doing this for a long time, and there is not one person in a hundred who has given as thorough and correct an answer as you just did."
There were other difficulties with getting this job, based on my short experience with specific technologies. I'm convinced, though, that this was the best part of my series of interviews, and it got my foot wedged pretty firmly in the door.
Writing software is fundamentally different from working on an assembly line. You don't solve the same problem twice. You don't write the same code twice. If you are repeating yourself, then you are in some way failing to leverage past experience. You should be moving the duplicated code into a common function, or a common library, or something, so you can stop working on problems that have already been solved, and get the business of making your program do something new and interesting.
Because of this non-repetitive approach, it's important to be able to think about every problem from multiple angles, to try and relate it to past experience and evaluate different kinds of solutions. Big O Notation is one tool for being able to evaluate how you're doing.