I have an int[]
array that contains values with the following properties:
Let's name the interval x
here and z
the searched number.
Since you expect the values to be evenly distributed, you can use interpolation search. This is similar to binary search, but splits the index range at start + ((z - x[start]) * (end - start)) / (x[end] - x[start])
.
To get a running time of O(log n)
you have to do combine interpolation search with binary search (do step from binary search and step from interpolation search alternating):
public int search(int[] values, int z) {
int start = 0;
int end = values.length-1;
if (values[0] == z)
return 0;
else if (values[end] == z) {
return end;
}
boolean interpolation = true;
while (start < end) {
int mid;
if (interpolation) {
mid = start + ((z - values[start]) * (end - start)) / (values[end] - values[start]);
} else {
mid = (end-start) / 2;
}
int v = values[mid];
if (v == z)
return mid;
else if (v > z)
end = mid;
else
start = mid;
interpolation = !interpolation;
}
return -1;
}
Since every second iteration of the while loop does a step in binary search, it uses at most twice the number of iterations a binary search would use (O(log n)
). Since every second step is a step from interpolation search, it the algorithm should reduce the intervall size fast, if the input has the desired properties.