Problem
Find the minimum element in the rotated sorted array.
For example, the array a = [0, 1, 2, 4, 6, 8, 10]
might become:
[8, 10, 0, 1, 2, 4, 6]
if it was rotated 2 times.[4, 6, 8, 10, 0, 1, 2]
if it was rotated 4 times.
Notice that rotating an array [a[0], a[1], a[2], ..., a[n-1]]
1 time results in the array [a[n-1], a[0], a[1], a[2], ..., a[n-2]]
.
Example
Example 1:
Input: nums = [5, 7, 9, 1, 3]
Output: 1
Explanation: The original array was [1, 3, 5, 7, 9] rotated 3 times.
Example 2:
Input: nums = [4, 6, 8, 10, 0, 1, 2]
Output: 0
Explanation: The original array was [0, 1, 2, 4, 6, 8, 10] and it was rotated 4 times.
Example 3:
Input: nums = [5, 10, 15, 20]
Output: 5
Explanation: The original array was [15, 10, 15, 20] and it was rotated 4 times.
Solution
The answer to this lies on the fact that if we can find the point on inflection and things will be simple. So if we can have 2 sub arrays A and B,
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).
Method 1 - Recursion
Define a helper function, otherwise, we will need to use Arrays.copyOfRange() function, which may be expensive for large arrays.
class Solution {
public int findMin(int[] nums) {
return findMin(nums, 0, nums.length - 1);
}
private 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;
// sorted array now - so 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);
}
}
}
Complexity
- ⏰ Time complexity:
O(log n)
- 🧺 Space complexity:
O(1)
Method 2 - Iterative Solution
Code
Java
class Solution {
/*
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 left = 0;
int right = nums.length - 1;
while (left <= right) {
if (nums[left] <= nums[right]) {
return nums[left];
}
int mid = (left + right) / 2;
if (nums[mid] >= nums[left]) {
left = mid + 1;
} else {
right = mid;
}
}
return -1;
}
}
Making above code smaller:
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right && nums[left] > nums[right]) {
int mid = left + (right - left) / 2;
if (nums[mid] > nums[end]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
}