This:
| A[i]−A[i+1] | ≤ 1
means that each element in your array will be at most one different(-ve or +ve). It then follows that the closest index that can contain z from the current is |A[cur] - z|
spaces away.
So, what you do is start with j=0
, and figure it out for each step. Jump that many spaces, and check again. Eventually you'll find z or reach the end.
public static int findZ(int[] a, int z){
int j = 0;
while(j < a.length){
if(a[j] == z)
return j
j += Math.abs(a[j] - z);
}
return -1;
}
This isn't a binary or exponential search, and it's not recursive, but it's simple and gets the job done. It works as a one-sided interpolation search. See below for the two-way method. You can turn it into a recursive function, but that should be straightforward and I'll leave that to you.
It runs in O(n), where your worst case performance is going to be on something like {0,0,0,0,1}
, where it can only jump one step, and turns into a straight linear search.
Best case will be ordered, distinct members like {0,1,2,3,4,5}
, where it will only perform one jump.
Edit:
In the interests of making this more "interpolation search-like", let's move both the upper and lower bounds at the same time. The same logic applies for both ends:
public static int findZ(int[] a, int z){
int j = 0;
int k = a.length - 1;
while(j <= k){
if(a[j] == z)
return j
if(a[k] == z)
return k;
j += Math.abs(a[j] - z);
k -= Math.abs(a[k] - z);
}
return -1;
}
It still ends up as O(n) overall worse case, but this is normal for an interpolation search.
Now your worst case is more like {0,0,0,1,0,0,0}
, and your best is like {0,1,2,3,2,1,0}
.