2

I have a sorted array of 5000 integers. How fast can I tell if a random integer is a member of the array? An answer in general, C and Ruby would be nice.

The array values are of the form

c * c + 1

where c can be any integer from 1 to 5000.

For example:

[2, 5, 10, 17, 26, 37, 50 ...]
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Auburnate
  • 437
  • 1
  • 4
  • 11
  • I'm not looking for subtract one and take the sqrt() and test if that is an int. ;) – Auburnate Jan 22 '09 at 20:06
  • Well, you could also look at http://stackoverflow.com/questions/295579/fastest-way-to-determine-if-an-integers-square-root-is-an-integer for other ways that don't involve looking through the array. – A. Rex Jan 22 '09 at 20:24
  • 2
    It's always O(1) for a fixed size ;) – Pete Kirkham Jan 22 '09 at 20:25
  • @A. Rex: I was going to recommend the same, but I still think sqrt would be slower than the max of 13 comparisons you'd have to do with binary search. I could be wrong. – Bill the Lizard Jan 22 '09 at 20:29
  • Are all values from 1-5000 in this array or are some multiple times in it? – Georg Schölly Jan 22 '09 at 20:38
  • Does it have to be in an array? As everyone else has noted, binary search will get you O(log N), but Tal the Perl guy is onto something. Hashing your array will reduce the time to O(1). – rtperson Jan 22 '09 at 20:45
  • This whole discussion is pointless. There is no conceivable reason to construct this array or search it in this manner. – PeterAllenWebb Jan 22 '09 at 21:45
  • Also pointless to discuss Big O running time of searching a constant sized array - O(1) by definition. – mbeckish Jan 22 '09 at 21:50
  • @Bill the Lizard: You're probably right. I just figured it was usefully related. =) – A. Rex Jan 23 '09 at 08:55

9 Answers9

16

log(n) for binary search on c

orip
  • 73,323
  • 21
  • 116
  • 148
10

I would say it's O(const)! :)

Given a random number r, it's trivial to check whether it's a number that could be represented in the form (n*n+1). Just check whether the sqrt(r-1) is an integer or not!

(Well, it might be a little more complicated than that since your programming language can introduce some complexity into dealing with integers vs floating point numbers, but still: you do not need to search the array at all: just check whether the number is in this particular form.)

kirillka
  • 181
  • 5
  • if this actually works, and it looks like it should, then you are a genius for figuring this out when everyone else looked at it as a search problem (including me). I wish I could upvote more than once... – rmeador Jan 22 '09 at 20:40
7

Binary search, as others have mentioned, is O(log2N), and can be coded either recursively:

   BinarySearch(A[0..N-1], value, low, high) {
       if (high < low)
           return -1 // not found
       mid = (low + high) / 2
       if (A[mid] > value)
           return BinarySearch(A, value, low, mid-1)
       else if (A[mid] < value)
           return BinarySearch(A, value, mid+1, high)
       else
           return mid // found
   }

or iteratively:

   BinarySearch(A[0..N-1], value) {
       low = 0
       high = N - 1
       while (low <= high) {
           mid = (low + high) / 2
           if (A[mid] > value)
               high = mid - 1
           else if (A[mid] < value)
               low = mid + 1
           else
               return mid // found
       }
       return -1 // not found
   }

However, if you're looking for the fastest possible way, you can set up a look up table based on the sqrt(N-1) of your numbers. With just 5,000 words of memory you can achieve O(1) lookups this way.

Explanation:

Since all your numbers are of the form N^2 + 1 for an integer N from 1 to N, you can create a table of N elements. The element at position i will specify if i^2 + 1 is in your array or not. The table can be implemented with a simple array of length N. It will take O(N) to build, and N words of space. But once you have the table, all lookups are O(1).

Example:

Here's sample code in Python, which reads like pseudocode, as always :-)

import math

N = 5000
ar = [17, 26, 37, 50, 10001, 40001]

lookup_table = [0] * N

for val in ar:
    idx = int(math.sqrt(val - 1))
    lookup_table[idx] = 1

def val_exists(val):
    return lookup_table[int(math.sqrt(val - 1))] == 1

print val_exists(37)
print val_exists(65)
print val_exists(40001)
print val_exists(90001)

Building the table takes up O(N) at most, and lookups are O(1).

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
5

Technically, the complexity of finding an element in a fixed-size array is constant, since log2 5000 isn't going to change.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
2

Binary Search is O(log n)

WikiPedia

JoshBerke
  • 66,142
  • 25
  • 126
  • 164
1

O(log n) if the array has n elements

raupach
  • 3,092
  • 22
  • 30
1

Just to expand on that: it's lg n tests, that is log2 n. That makes it O(log n). Why? because each trial of a binary search divides the array in half; thus it takes lg n trials.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
0

Using a binary search, it's Log(N) search time.

bool ContainsBinarySearch(int[] array, int value) {
  return Array.BinarySearch(arrray, value) >= 0;
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
0

In Perl:

I would load the values into a static hash and then it would be O(1).

Build the Lookup hash

lookup_hash{$_} = 1 foreach (@original_array);

Lookup syntax

($lookup_hash{$lookup_value}) && print "Found it in O(1) - no loop here\n";

Community
  • 1
  • 1
  • Just because the "visible" code is one statement long, that doesn't make the actual lookup O(1). A hash lookup is not a constant-time operation, it's dependent upon the size of the hash and the specific lookup algorithm (not sure which one Perl uses internally). – DanM Jan 22 '09 at 20:56
  • DanM - actually, Perl's hashing will be very close to O(1), especially for this amount of elements (i.e. not very large) – Eli Bendersky Jan 22 '09 at 21:09