Suppose I have a sorted array [1, 2, 3, 4, 5, 6]
. I can apply binary search to find any number but what modification in my binary search logic I have to do If my sorted array shifted left by some unknown number. Like [4, 5, 6, 1, 2, 3]
.

- 57,103
- 20
- 141
- 208

- 11,912
- 6
- 43
- 80
-
Do you know the amount of the shift? – Jay Feb 11 '15 at 19:15
-
hmmm im not sure if you can then use binary search if it is an unknown shift. – jgr208 Feb 11 '15 at 19:15
-
i guess you can edit to find the lowest value to the right and then start the search from there, how ever it really breaks any efficient logic, the path i see is a sort then binary search. – jgr208 Feb 11 '15 at 19:16
-
@jay i don't know the number of shift . – Sumeet Kumar Yadav Feb 11 '15 at 19:17
-
Are all values unique? – kraskevich Feb 11 '15 at 19:18
-
@kraskevich Assume all values are unique . – Sumeet Kumar Yadav Feb 11 '15 at 19:20
-
possible duplicate of [Searching in an sorted and rotated array](http://stackoverflow.com/questions/4773807/searching-in-an-sorted-and-rotated-array) – 500 - Internal Server Error Feb 11 '15 at 19:32
5 Answers
We can find the shift using binary search. We need to find the first number which is less than the first element of the given array. Something like this:
def getShift(): if a[n - 1] > a[0]: return 0 // there is no shift low = 0 // definitely not less than a[0] high = n - 1 // definitely less than a[0] while high - low > 1: mid = (low + high) / 2 if a[mid] < a[0]: high = mid else low = mid return high
Now know the shift so we can run standard binary search over two intervals:
[0, shift)
and[shift, n - 1]
.
The time complexity is O(log n)
(because we run 3 binary searches).

- 18,368
- 4
- 33
- 45
-
1Finally, a real solution to the problem that doesn't involve wasting the knowledge of having almost sorted list. +1 – amit Feb 11 '15 at 19:31
-
It is not necessary to locate where the shift is; you can do the normal binary search with a simple modification by comparing `a[mid]` and the searched for value `x` with `a[0]` at the same time. See my answer. – Matt Feb 12 '15 at 20:19
Just re-sort the array after the unknown shift. It will be computationally expensive, but it will be correct.
Additionally, you could also just do a linear sort at this point, since sorting and searching will take O(n*log(n)). Doing a linear search via brute force will only be O(n).

- 4,560
- 5
- 21
- 35
-
yes, since this would be more efficient and less error prone then trying to reinvent the wheel to say with a modified binary search – jgr208 Feb 11 '15 at 19:18
-
Sorry, but I really dislike this answer. "computationaly expansive" by exponential factor, this approach will be approximately as efficient as just doing a linear search - both are correct, and both takes exponential more time than binary search – amit Feb 11 '15 at 19:24
-
-
I dislike the answer because I am pretty sure there should be exponentially better solution to it, yes. (Unless you argue you cannot modify binary search, and even then - linear scan is still more efficient). Correctness is not everything, efficiency is also an issue. Hack, why not just do a [monkey sort](http://en.wikipedia.org/wiki/Bogosort) on the array and then search? – amit Feb 11 '15 at 19:27
-
2Well yes, there most likely is. But in a real world of deadlines and management, sometimes we don't have time to come up with elegant solutions. This is quick and it works. – Lawrence Aiello Feb 11 '15 at 19:27
-
@amit i argue you can not without wasting more memory of a computer, to modify a binary search also yes linear is efficient but imagine the list is large and the number is at the very end you want to find. – jgr208 Feb 11 '15 at 19:28
-
Linear scan is quicker both to implement and to run and it works too, so there is a simpler AND more efficient solution. – amit Feb 11 '15 at 19:28
-
@jgr208 So what? Linear scan will traverse the list once - each element is scanned exactly once. If you sort, you need to traverse each element O(logn) times (on average), and for this special modification of the array - you are much more likely to fall into the worst cases of algorithms such as quick sort (and make the run time quadric) – amit Feb 11 '15 at 19:30
-
-
2Actually yes....he is right. Sorting and searching will take O(n log(n)) where as linear search takes O(n). I will update the answer. – Lawrence Aiello Feb 11 '15 at 19:33
You only need to run through the regular binary search algorithm once, with a modification on the logic as to when to select the upper or lower search window. The modification is based on additional comparisons with the first element in the shifted array so that you know which segment of the array you are in. You can do this without having to actually find the precise location of the split.
In ruby:
LIST = [6,7,8,9,10,1,2,3,4,5]
def binary_search(x)
first = LIST[0]
low = 0
high = LIST.size-1
while low <= high
mid = low + (high-low)/2 # avoid overflow
return mid if x == LIST[mid]
if (LIST[mid] < first) != (x < first) || LIST[mid] < x
low = mid + 1
else
high = mid - 1
end
end
return -1 # not found
end
1.upto(10) do |x|
puts "#{x} found at index #{binary_search(x)}"
end
Output:
1 found at index 5
2 found at index 6
3 found at index 7
4 found at index 8
5 found at index 9
6 found at index 0
7 found at index 1
8 found at index 2
9 found at index 3
10 found at index 4

- 20,108
- 1
- 57
- 70
Method 1
Actually with an unknown shift you can still do a binary but its kinda wonky.
One method is doubling the size of the list i.e:
[4,5,6, 1,2,3, 4,5,6, 1,2,3]
# basically mylist.extend(mylist)
As you can see I just doubled the size but the middle section is still ordered.
Now you can go through the list until
list[i-1] > list[i]
This will be you start of the binary search and the same amount at the end would be the end of your binary list.
start = i
end = len(list) -1
Now you can do the binary search
Depending of the data average could be lower then O(n)
Method 2
You can resort the list and do the the binary search:
O(nlog(n)) + log(n)
Method 3
Linear search of all elements
O(n)

- 2,656
- 1
- 16
- 24
-
If we go through the entire list to find `list[i - 1] > list[i]`, it is easier to use a simple linear search(the time complexity is the same in the worst case). – kraskevich Feb 11 '15 at 19:21
-
that is true, and this also uses more memory of the computer. so would not be good for an embedded application. – jgr208 Feb 11 '15 at 19:22
-
True about big-o but on average (depending on the data) it could be faster especially if the shift is small. – Jay Feb 11 '15 at 19:24
Just simple binary search without doubling or sorting or any other preprocessing of array
so lets start
l = 0;
r = n-1;
and
m = (l + r)/2
if we are searching for value v than:
1) if (there is no jump between l and m)
array[l] < v < array[m] or
(if there is jump between l and m)
v < array[m] < array[l] or
array[m] < array[l] < v
than v is between l and r, and we can make r = m
2) if v is equal to array[l] array[r] or array[m] we found it
3) in all others cases v is somewhere between m and r and we can make l = m
4) repeat for new l and r

- 861
- 4
- 11