把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
分三种情况:
第一种情况:
数组:[1, 2, 3, 4, 5] 1和2旋转后数组尾部,旋转后为:[3, 4, 5, 1, 2]
第二种情况:
数组:[1, 2, 3, 4, 5] 整体旋转,旋转后不变,仍为:[1, 2, 3, 4, 5]
第三种情况:
数组:[1, 1, 1, 1, 1] 不管怎么旋转,旋转后都为:[1, 1, 1, 1, 1]
从前往后遍历,后一个数比前一个数小,则后一个数就是最小数,否则最小数是数组的第一个元素。(因为未旋转前的原始数组是递增排序的)
class Solution {
public int minArray(int[] numbers) {
int n = numbers.length;
for (int i = 0; i + 1 < n; i++) {
if (numbers[i] > numbers[i+1]) {
return numbers[i+1];
}
}
return numbers[0];
}
}
倘若想要效率高点就得二分,在此之前我们依然先观察一下数组,正常情况下:如[3,4,5,1,2]
以旋转处分界,**首先左半部分任意一个数一定都大于右半部分任意一个数,**因而
当mid的值大于right时,此时说明mid一定定位在左半部分,那么区间就可以缩小到[mid+1,right]
当mid的值小于right时,说明mid此时一定定位在右半部分,且要么直接定位在旋转处,要么直接定位在旋转处的右边,区间缩小到[left,mid]
当mid的值等于right时,此时是最棘手的,正常情况不会出现这种现象,但是当数组中混有大量重复元素时就会有这样的情况,此时无法判断出具体的情况,比如:
两个旋转点值为 0 的示例数组,则当 left = 0, right = 4 时 mid = 2 ,两示例结果不同。
示例一 [1, 0, 1, 1, 1] :旋转点 x = 1 ,因此 mid = 2 在右排序数组中。
示例二 [1, 1, 1, 0, 1] :旋转点 x = 3 ,因此 mid = 2 在左排序数组 中。
此时经过复杂的数学推论得出处理手段是进一步缩小区间让right=right-1
而复杂的逻辑推论先不作解释,链接放这:链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-
class Solution {
public int minArray(int[] numbers) {
int i = 0, j = numbers.length - 1;
while (i < j) {
int m = (i + j) / 2;
if (numbers[m] > numbers[j]) i = m + 1;
else if (numbers[m] < numbers[j]) j = m;
else j--;
}
return numbers[i];
}
}