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 can 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
/* 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; } |
I think `return -1` is unclear.
I would expect a more precise while condition.
I also found this awesome tutorial.
https://www.youtube.com/watch?v=IrraEhe9xIQ
public int minElementRotatedSortedArray(int[] ary) {
if(ary == null || ary.length ary[endPoint]) {
startPoint = midPoint + 1;
midPoint = startPoint + ((endPoint - midPoint) / 2);
} else if(startPoint == midPoint || midPoint == endPoint || ary[midPoint] < ary[midPoint-1]) {
return ary[midPoint];
} else {
endPoint = midPoint-1;
midPoint = (startPoint+endPoint)/2;
}
}
}
A JavaScript Solution with Video Explains
https://www.youtube.com/watch?v=uiBf_DHxgd0
Because you rotated it wrong. The pivot is not a stationary number in this question. SO you don’t keep 4 locked.
Solution doens’t work for {5, 6, 7, 4, 0, 1, 2}. I rotated {0, 1, 2, 4, 5, 6, 7} in the middle and then try to find the minimum. It is showing ‘4’ instead of ‘0’
No it takes O(n) time even without dups
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) ;
}
The above proposed algorithm works in O(logn), since the problem statement says no duplicates.
The problem is itself about using binary search .. Why use O(n) solution? that a very obvious solution 😛
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];
}