Reputation: 21
I have an array of unknown length n
, where each element of the array is the number 1. So its like A=[1,1,1,1.....]
, n
times. Now I need to write an algorithm to find out the value of n
.
Here is the full problem statement:
You are given an array
A
of lengthn
. Each value is 1. However, you do not know what the value ofn
is. You are allowed to access an elementi
of the array by callingA[i]
. Ifi < n
, this will return 1, and ifi >= n
, this will return a message saying that the location does not exist (you can think of this as an error message, but it will not crash your program). Describe an O(log n) algorithm to determine the value ofn
.
This is what I have come up with :
Set i = 1;
while A(i-1) is true // i.e. for i <= n, it will return the element for the index (i-1)
print i_old = i
print i_new = 2i // doubling the value of i
i = i_new // to run the loop again to check the array A with new value of i
else
print no element found // when i>n
Now, this means the last index is between the last pair of i_old
and i_new
.
So, for an array [1,1,1,1,1,1]
of six elements the value of n
can be between 4 and 6, i.e. it can be either 4 or 5.
I am not sure about how to proceed further. What am I missing?
Upvotes: 0
Views: 1327
Reputation: 56965
We can solve this using the exponential search algorithm in O(log n) time:
Assume the length is 2. Try successive powers of 2 (2, 4, 8, 16...) until an out of bounds exception is raised. This gives a guarantee of an upper bound on the possible length. Perform a right binary search between 0 and this upper bound. On each bisection iteration, if the midpoint index doesn't raise an exception, try the upper half of the search space, else try the lower half. When our bounds meet, return that index.
Python implementation:
def length(L):
lo = 0
hi = 1
while 1:
hi *= 2
try:
L[hi]
except IndexError:
break
while lo < hi:
mid = (lo + hi) // 2
try:
L[mid]
lo = mid + 1
except IndexError:
hi = mid
return hi
if __name__ == "__main__":
assert all(length([1] * i) == i for i in range(1000))
Upvotes: 1