题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个 非递减 排序的数组的一个旋转,输出旋转数组的最小元素。例如数组 {3, 4, 5, 1, 2} 为 {1, 2, 3, 4, 5} 的一个旋转,该数组的最小值为 1。
NOTE:若数组大小为 0,请返回 0。
测试用例
- 功能测试(输入的数组是非递减排序数组的一个旋转,数组中有重复的数字或者没有重复的数字)
- 边界值测试(输入的数组是一个非递减排序的数组,只包含一个数字的数组)
- 特殊输入测试(输入空指针)
题目考点
- 考察应聘者对二分查找的理解。如果遇到从排序的数组中查找数字需要尝试二分查找法。
- 考察应聘者的沟通能力和学习能力。如果面试官提出新的概念,那么我们可以主动和面试官沟通,多问几个问题,把概念弄清楚。
- 考察应聘者思维的全面性。排序数组本身是一个数组旋转的一个特例,另外,我们需要考虑到数组中有相同数字的特例。
解题思路
如果遇到从排序的数组中查找数字需要尝试二分查找法。
我们利用两个指针分别指向数组的第一个元素和最后一个元素,我们可以先找到数组中间的元素,如果该中间元素大于或等于第一个元素,则位于前面的非递减子数组,此时我们就可以把第一个指针指向该中间元素,这样就可以缩小寻找的范围,移动以后,第一个指针依然指向前面的非递减数组;否则属于后面的非递减子数组,此时我们就可以把第二个指针指向该中间元素,移动以后,第二个指针依然指向后面的非递减数组。然后循环下去,最终第一个指针将指向前面子数组的最后一个元素,而第二个指针将会指向后面子数组的第一个元素,而第二个指针指向的刚好是最小的元素。循环结束。
PS:我们要注意的在参考解题中main函数里的特例,如果两个指针以及中间的元素指向的三个数字相等,就只能顺序查找。
代码
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];
}
}