题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
思路:
- 由上图可知,旋转数组是由两个有序的数组来组成的,阴影和非阴影两部分对应两个有序的数组。定义两个索引p1和p2,分别指向数组的第一个和最后一个元素。
- 此时p1为0,p2为4,计算middle=(p1+p2)/2的值为2,值为5,和p1、p2所对应的值3和2进行对比,发现大于p1,说明middle处在前一个递增数组中,最小值应该在另外一个数组中,把p1的值赋值为middle,即指向的元素为5,如图b所示。
- 此时p1和p2的值指向的元素为5和2,继续获取middle值为3,对应元素为1,发现array[middle]小于array[p1],小于array[p2],可知,middle元素在后一个递增数组中,最小值应该在middle处或者它的前面,p2赋值middle,如上图所示,p1和p2紧挨着,p2即为最小值。
代码如下:
private static int binarySearch(int[] arrays) {
int p1 = 0;
int p2 = arrays.length - 1;
int middle = p1;
while (arrays[p1] >= arrays[p2]) {
if (p1 == p2 -1) {
middle = p2;
break;
}
middle = (p1 + p2) / 2;
int middleValue = arrays[middle];
if (middleValue > arrays[p1]) {
// 在前面的递增子数组中,最小值在middle后面
// p1移到middle的位置
p1 = middle;
} else if (middleValue < arrays[p2]) {
// 在后面的递增子数组中,最小值在在middle前面
// p2移到middle位置
p2 = middle;
} else if (middleValue == arrays[p1]) {
// 进行顺序查找
return inOrderSearch(arrays);
}
}
return arrays[middle];
}
主要核心点:
- 理解该旋转数组,可拆分为两个有序数组,通过定义的两个p1h和p2来不断缩小查找范围。
- 需要考虑一个原始的递增数组{1,2,3,4,5,6}本身也是一个旋转数组(通过while循环来判断);middle对应元素的值和p1/p2对应的值相等,采用顺序查找。