views:

987

answers:

2

I had this question:

Given an unsorted array of positive integers and an integer N, return N if N existed in the array or the first number that is smaller than N.

in an interview and wanted to know what would be the best efficient algorithm to solve it?

I had given two approaches using hash and sorting array but it was not correct and efficient approach. I would really appreciate if someone can give an optimal algorithm for this problem.

+11  A: 

I'm assuming this is in a C-style language; if not, please update the question to reflect the language.

If the array isn't sorted, then you have no choice but a (potentially) full traversal of the array to look for N, as any sorting operation is going take longer than simply traversing the array (other than by finding the element by "blind luck"). Something akin to this would probably be the most efficient (unless I'm missing something)

int retVal = -1;

for(int i = 0; i < ARRAY_LENGTH; i++)
{
    if(array[i] == N) return N;
    if(retVal == -1 && array[i] < N) retVal = array[i];
}

return retVal;

As suggested elsewhere, you can modify

if(retVal == -1 && array[i] < N) retVal = array[i];

to

if(retVal < array[i] && array[i] < N) retVal = array[i];

In order to get the largest value that's smaller than N, rather than simply the first.

Adam Robinson
Wouldn't it be better to check for retVal == -1 first in the last comparison? Once it's set, you shouldn't have to look for anything else other than N itself.
Chris Farmer
@Chris: Good catch, thanks; corrected.
Adam Robinson
If you *really* care about not doing unnecessary comparisons, you could split it into two loops. The first one is like the one you have now, but it stops when you find an element smaller than N. The second one takes off where the first one stopped and only does the `if (array[i] == N) return N;` part.
Joren
+11  A: 

Scan through the list from beginning to end, if you see a value less than N, hold on to the first one until you reach the end, or find N. If you find N, return it, if you reach the end, return the value you've held on to. Presumably there'd have to be some value to return if all the values were greater than N, but the problem doesn't state that.

O(N) performance, O(1) space usage.

It's a little trickier if you're looking for the largest value smaller than N. In which case, instead of holding on to the first value smaller than N, you simply grab a new value every time you find a value smaller than N, but larger than the value you are currently holding on to.

Simply replace

if(array[i] < N && retVal == -1) retVal = array[i];

with

if(array[i] < N && retVal < array[i]) retVal = array[i];

in Adam's answer

Eclipse
From OP: "First number smaller than N" you think that is the first number in the array?
AnthonyWJones
@Eclipse: What would be approach if we are looking for the number closest to N while being smaller than N instead of first less number than N ?
Rachel
Odd, accepted answer that directly refers to mine for actual code.
Adam Robinson
@Adam, Yup, I upvoted your answer since we basically hit the same answer at the same time, you just one-upped me by supplying sample code. Not sure why mine was accepted over yours.
Eclipse
@Eclipse, not to quibble but mine was also more than a minute earlier. ;)
Adam Robinson
Exactly! There must be more to the question, for that isn't much of an algorithm, unless that is one of these aimed at testing the candidates ability to read carefully rather that to have elaborate coding talent.
mjv
@Anthony: I agree that this seems like a weird question. The slightly more fun problem is the largest integer that's smaller than N.
Chris Farmer