Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binary search to find the rotation point in a rotated sorted list

I have a sorted list which is rotated and would like to do a binary search on that list to find the minimum element.

Lets suppose initial list is {1,2,3,4,5,6,7,8} rotated list can be like {5,6,7,8,1,2,3,4}

Normal binary search doesn't work in this case. Any idea how to do this.

-- Edit

I have one another condition. What if the list is not sorted??

like image 381
Boolean Avatar asked May 09 '10 02:05

Boolean


People also ask

How do you find the rotation point in a sorted array?

Approach to Find the Point of RotationStart traversing the array from the beginning. There will be a index in the array where the value stored at the index will be smaller than the value at the previous index. Return the index.

Does binary search work on rotated array?

You can use binary search on the rotated array (with some modifications). Let N be the number you are searching for: Read the first number (arr[start]) and the number in the middle of the array (arr[end]):


1 Answers

A slight modification on the binary search algorithm is all you need; here's the solution in complete runnable Java (see Serg's answer for Delphi implementation, and tkr's answer for visual explanation of the algorithm).

import java.util.*;
public class BinarySearch {
    static int findMinimum(Integer[] arr) {
        int low = 0;
        int high = arr.length - 1;
        while (arr[low] > arr[high]) {
            int mid = (low + high) >>> 1;
            if (arr[mid] > arr[high]) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }
    public static void main(String[] args) {
        Integer[] arr = { 1, 2, 3, 4, 5, 6, 7 };
        // must be in sorted order, allowing rotation, and contain no duplicates

        for (int i = 0; i < arr.length; i++) {
            System.out.print(Arrays.toString(arr));
            int minIndex = findMinimum(arr);
            System.out.println(" Min is " + arr[minIndex] + " at " + minIndex);
            Collections.rotate(Arrays.asList(arr), 1);
        }
    }
}

This prints:

[1, 2, 3, 4, 5, 6, 7] Min is 1 at 0
[7, 1, 2, 3, 4, 5, 6] Min is 1 at 1
[6, 7, 1, 2, 3, 4, 5] Min is 1 at 2
[5, 6, 7, 1, 2, 3, 4] Min is 1 at 3
[4, 5, 6, 7, 1, 2, 3] Min is 1 at 4
[3, 4, 5, 6, 7, 1, 2] Min is 1 at 5
[2, 3, 4, 5, 6, 7, 1] Min is 1 at 6

See also

  • Java Collections.rotate() with an array doesn’t work
    • Explains why Integer[] instead of int[]
  • Google Research Blog: Nearly All Binary Searches and Mergesorts are Broken
    • Explains why >>> 1 instead of / 2

On duplicates

Note that duplicates makes it impossible to do this in O(log N). Consider the following bit array consisting of many 1, and one 0:

  (sorted)
  01111111111111111111111111111111111111111111111111111111111111111
  ^

  (rotated)
  11111111111111111111111111111111111111111111101111111111111111111
                                               ^

  (rotated)
  11111111111111101111111111111111111111111111111111111111111111111
                 ^

This array can be rotated in N ways, and locating the 0 in O(log N) is impossible, since there's no way to tell if it's in the left or right side of the "middle".


I have one another condition. What if the list is not sorted??

Then, unless you want to sort it first and proceed from there, you'll have to do a linear search to find the minimum.

See also

  • Wikipedia | Selection algorithm | Linear minimum/maximum algorithms
like image 99
polygenelubricants Avatar answered Sep 26 '22 02:09

polygenelubricants