LeetCode – Find Minimum in Rotated Sorted Array (Java)

Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.You may assume no duplicate exists in the array.

Analysis

This problem is a binary search and the key is breaking the array to two parts, so that we only need to work on half of the array each time.

If we pick the middle element, we can compare the middle element with the leftmost (or rightmost) element. If the middle element is less than leftmost, the left half should be selected; if the middle element is greater than the leftmost (or rightmost), the right half should be selected. Using recursion or iteration, this problem can be solved in time log(n).

In addition, in any rotated sorted array, the rightmost element should be less than the left-most element, otherwise, the sorted array is not rotated and we can simply pick the leftmost element as the minimum.

Java Solution 1 - Recursion

Define a helper function, otherwise, we will need to use Arrays.copyOfRange() function, which may be expensive for large arrays.

public int findMin(int[] num) {
	return findMin(num, 0, num.length - 1);
}
 
public int findMin(int[] num, int left, int right) {
	if (left == right)
		return num[left];
	if ((right - left) == 1)
		return Math.min(num[left], num[right]);
 
	int middle = left + (right - left) / 2;
 
	// not rotated
	if (num[left] < num[right]) {
		return num[left];
 
	// go right side
	} else if (num[middle] > num[left]) {
		return findMin(num, middle, right);
 
	// go left side
	} else {
		return findMin(num, left, middle);
	}
}

Java Solution 2 - Iteration

public int findMin(int[] nums) {
    if(nums==null || nums.length==0)
        return -1;
 
    if(nums.length==1)
        return nums[0];
 
    int left=0;
    int right=nums.length-1;
 
    //not rotated
    if(nums[left]<nums[right])
        return nums[left];
 
    while(left <= right){
        if(right-left==1){
            return nums[right];
        }
 
        int m = left + (right-left)/2;
 
        if(nums[m] > nums[right])
            left = m;
        else
            right = m;
    }
 
    return nums[left];
}

Or

/*
To understand the boundaries, use the following 3 examples:
[2,1], [2,3,1], [3,1,2]
*/
public int findMin(int[] nums) {
    if(nums==null || nums.length==0)
        return -1;
 
    int i=0; 
    int j=nums.length-1;
 
    while(i<=j){
        if(nums[i]<=nums[j])
            return nums[i];
 
        int m=(i+j)/2;
 
        if(nums[m]>=nums[i]){
            i=m+1;
        }else{
            j=m;
        }
    }
 
    return -1;
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Shariq Aziz

    No it takes O(n) time even without dups

  • Larry Okeke


    public static void solution(){

    arr = new int[] {6, 7, 8, 9, 1, 2, 3, 4, 5};

    int solut = recurse(0, 4, 8);

    }

    public static int recurse(int l, int middle, int r){

    log("l: " + arr[l] + " r: "+ arr[r]);

    if(r - l <= 2) return (arr[l] < arr[r]) ? arr[l] : arr[r];

    if(arr[l] arr[l])

    return recurse(l, (middle/2)+1, middle);

    return recurse(middle, middle + middle/2, r) ;

    }

  • karthik varma

    The above proposed algorithm works in O(logn), since the problem statement says no duplicates.

  • Mr. Lazy

    The problem is itself about using binary search .. Why use O(n) solution? that a very obvious solution 😛

  • Burhan COKCA

    Simpler solution with O(n) time complexity in worst case.

    public int findMin(int[] nums) {

    if(nums.length == 1) return nums[0];

    for(int i =0; i nums[i+1])

    return nums[i+1];

    }

    return nums[0];

    }