旋转矩阵的最小数字
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 {3, 4, 5, 1, 2} 为 {1, 2, 3, 4, 5} 的一个旋转,该数组的最小值是1。
思路:
- 和二分查找一样,我们用两个指针分别指向数组的第一个元素和最后一个元素。接着我们寻找数组中间的元素。如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。这样我们可以把第一个指针指向该中间元素,这样可以缩小寻找的范围。移动之后第一个指针仍然位于前面的递增子数组。
- 同样,如果中间元素位于前面的递增子数组,那么它应该大于或者等于第一个元素指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。我们把第二个指针移动到中间元素的位置,也可以缩小范围。
- 重复①②步知道 right - left = 1 为止。
- 特殊情况 1:旋转矩阵旋转了 0 个元素(即根本没有旋转)。
- 特使情况 2:0 1 1 1 1 旋转两个元素之后变成 1 1 1 0 1。此时左边元素、右边元素和中间元素均是1,无法判断这个 1 是属于左边的还是属于右边的。
代码实现:
public static int getMin(int[] arr) {
int left = 0;
int right = arr.length - 1;
if(arr[left] < arr[right]) {
return arr[left];
}
while(right - left != 1) {
int mid = left + (right - left) / 2;
if(arr[mid] == arr[left] && arr[mid] == arr[right]) {
int index = left;
int min = arr[index];
for(int i = left; i <= right; i++) {
if(min > arr[i]) {
min = arr[i];
index = i;
}
}
return arr[index];
} else {
if(arr[mid] >= arr[left]) {
left = mid;
} else if(arr[mid] <= arr[right]) {
right = mid;
}
}
}
return arr[right];
}