Given an array, such as [7,8,9,0,1,2,3,4,5,6], is it possible to determine the index around which a rotation has occurred faster than O(n)?
With O(n), simply iterate through all the elements and mark the first decreasing element as the index.
A possibly better solution would be to iterate from both ends towards the middle, but this still has a worst case of O(n).
(EDIT: The below assumes that elements are distinct. If they aren’t distinct, I don’t think there’s anything better than just scanning the array.)
You can binary search it. I won’t post any code, but here’s the general idea: (I’ll assume that
a >= bfor the rest of this. Ifa < b, then we know it’s still in its sorted order)Take the first element, call it
a, the last elementb, and the middle element, calling itc.If
a < c, then you know that the pivot is betweencandb, and you can recurse (withcandbas your new ends). Ifa > c, then you know that the pivot is somewhere between the two, and recurse in that half (withaandcas ends) instead.ADDENDUM: To extend to cases with repeats, if we have
a = c > bthen we recurse withcandbas our ends, while ifa = c = b, we scan fromatocto see if there is some elementdsuch that it differs. If it doesn’t exist, then all of the numbers betweenaandcare equal, and thus we recurse withcandbas our ends. If it does, there are two scenarios:a > d < b: Here,dis then the smallest element since we scanned from the left, and we’re done.a < d > b: Here, we know the answer is somewhere betweendandb, and so we recurse with those as our ends.In the best case scenario, we never have to use the equality case, giving us
O(log n). Worst case, those scans encompass almost all of the array, giving usO(n).