剑指 Offer 11. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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
解题思路
二分法: 对于一个递增有序(不是严格递增, 可能有重复)的数组的旋转, 旋转之后的特点可能如下:分为两部分递增有序, 并且最后一个数, 小于等于第一个数(实际发生了旋转之后)。
所以二分的策略如下, 每次把中间值mid和最右边元素比, 如果大于最右边元素, 则此mid一定落在左半边的递增数组, 此时, 应当排除掉[left, mid], 新区间为[mid+1, right]。如果mid值小于最右边元素, 则此mid一定落在右半边, 此时应当排除掉区间(mid, right], 新区间为[left, mid]; 当前值等于最右边值, 此时没法确定当前的mid值落在最左边还是最右边, 但是也不能什么都不做(不改变区间大小的话, 就会死循环), 所以这时, 可以让右指针向左移一位, 不会对结果产生影响。
public int minArray(int[] numbers) {
int left = 0, right = numbers.length - 1;
int mid = 0;
while (left < right) {
mid = (left + right) >> 1;
if (numbers[mid] > numbers[right]) {
left = mid + 1;
} else if (numbers[mid] < numbers[right]) {
right = mid;
} else {
right--;
}
}
return numbers[left];
}