Of course, either way the algorithm runs in O(log n) time.
Of course, either way the algorithm runs in O(log n) time.
As for my case, I did attempt to start at an arbitrarily large number (but he wouldn't let me), and then went up exponentially (i.e. x = x * x), bi-secting the space once the upper-bound was found and solving from there.
My interviewer was sadly not that bright and didn't understand my solution, forcing me to re-write it -- incidentally, lecturing me on how wonderful O(log n) is along the way.
Closer to 0 than what? Infinity? By any reasonable definition, every integer is closer to 0 than infinity.
I think the problem as stated is underspecified; I disagree that increasing "exponentially" (the solution your interviewer described would increase exponentially; your version is doubly exponential, I think) is always faster. Both versions have the same worst-case running time, and if you want to talk about expected running time you need to make assumptions about the data distribution. As a counterexample, if you start with an initial guess of 2 and keep squaring, but the true number is 2^1025, then you end up doing much more work than if you had doubled instead of squaring.
I can certainly agree with you that lecturing in an interview is unproductive. Not only is it understandably off-putting, but it doesn't give the interviewer any additional input to the hiring decision and therefore is a waste of everyone's time. (Unless one of the job requirements is coping well with being lectured to, I guess.)
Perhaps, but originally we weren't discussing 0, we are starting with an arbitrarily large number. This problem is exacerbated when you say:
> I disagree that increasing "exponentially"... is always faster ... Both versions have the same worst-case running time
Worst case, sure, but how do you compute average? You could take a selection of n number of integers from 0 to infinity and the number of guesses until you found the correct answer, but of course you can't do this because you can't easily get a random number to test with that is between 0 and infinity. That said, it is fairly clear that x * x is faster than 2x is faster than x+1, but you can only prove this to be true once you pick an arbitrary limit less than infinity -- and the benefits of the better algorithm are only evident as you approach infinity.
Seems like a catch 22. Perhaps there is some expert in set theory as applied within computer science that can provide the appropriate formal context for determining the better algorithm in this context.
As for O notation, it is an interesting tool but one that has no application within any realm of actual programming in which I have worked, and I have never bothered to learn it simply to dazzle people in algorithm-based interviews (perhaps because I do more nuts and bolts type work rather than optimization).
------------------
1. In the initial probing for the upper bound, there is no point to grow faster than 2x each time
If we double the probe each time, we'll find the upper bound in O(log N) time. Then, we'll need O(log N) additional time to find the real answer. That makes the entire algorithm O(log N).
Suppose instead, in the initial probing we grow the bound faster, say by squaring each time. We'll find the upper bound faster, but we'll still need additional O(log N) time to find the real answer. So, we didn't really make the algorithm (asymptotically) faster - it is still O(log N).
(I glossed over some details in the explanation, but even if you work out the math exactly - which is not that hard to do - the conclusion holds.)
------------------
2. There is no point starting from a number greater than 1
There is no way to pick a "good" starting number - should it be 1,000? 1,000,000,000? 10^100? (10^100)^100? You might as well start from 1. That way, you guarantee that you'll find small numbers fast and large numbers still in an asymptotically optimal time.
------------------
As someone with fairly strong theoretical computer science backgound, I can see the intended meaning behind the interviewer's question and answer. But, it is a theoretical question. There definitely are a lot of highly valuable software developers out there who couldn't answer it.
I suppose I'm at a loss for words, since as a seasoned software developer without a deep background in theoretical computer science, it seems that I am being told to disregard my intuition based on experience in favor of a theoretical model that seems to ignore actual problem sets. Am I missing something?
https://gist.github.com/3839551
AFAICT, the parent and the interviewer is right because both methods run in roughly the same time because the time of the binary search is orders of magnitude greater than the upper bound finding part. I might have made one or more mistakes though.
The first observation that I have is that given that the secret number s is chosen, the first step can be completed arbitrarily quickly. One could use a function that rises arbitrarily fast. Imagine for example the function taking k to the Ackerman function A(2,2,k). That rises so fast it's incomprehensible, but really one could easily produce a function which rises faster still (the algorithm that picks s first!). The problem is, though, of how fast a fixed algorithm is for random s. If s is truly chosen at random from the positive integers, this leads to problems. Fix your putative algorithm. Suppose for the moment that it starts at 0 (it is not going to matter where it starts) What is the probability that the kth number that your function spits out is less than a random integer? 100% After all, how many integers are greater than any given integer?
Therefore, no growth function is any better on average at finding the upper bound than any other. Therefore step 1) is an insoluble problem. The problem should have been specified in some other way in order for it to make sense.
However, the second step involves log_2(n) time (in the worst-case-scenario and still O(log n) in general) where n is the upper bound --the output of step 1-- which means that the time to complete the algorithm is (Time of step 1 to find n) + O(log n). IF the problem made sense and it was the case that step 1) were soluble, then it would matter how fast step 1 is countered by the degree to which step 1 tends to overshoot the secret number --because overshooting by k has the penalty of log(k) extra operations.
Is there are framework in which question 1 makes sense? It would make sense if there were a given probability distribution on the integers (a function on the positive integers whose sum over all integers = 1, for example choose the function f(n) = 6/(n^2 * pi^2)) A probability distribution gives you a way of answering the question: "what proportion of the positive integers are greater than k?"
In retrospect, I might have mentioned this and then gave the interviewer's preferred answer in code, just to keep things simpler.