【题11 旋转数组的最小数字】
【题目】
把一个数组最开始的若干个元素都搬到数组的末尾,称之为数组的旋转。
输入一个递增排序的数组的一个旋转,输出的旋转数组的最小元素。
例如:数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
分析:
(1) 两个指针,分别指向第一个元素和最后一个元素,(第一个元素大于等于第二个元素(有特例))
(2) 找到中间元素,如果中间元素位于前面递增子数组,则中间元素大于等于第二个指针指向的元素,此时最小元素位于该中间元素的后面,查找范围缩小。
(3) 如果中间元素位于后面的递增子数组,中间元素小于等于第二个指针指向的元素,此时最小元素位于该中间元素前面,查找范围缩小。
(4) 最终会指向两个相邻元素,而第二个指针指向的刚好是最小元素,循环结束
例
注:
由于把递增排序数组前面的若干个数字搬到数组的后面,所以第一个数字总大于等于最后一个数。
特例:
如果把排序数组的前面的0个元素搬到最后面,即排序数组本身,这仍是数组的一个旋转,代码需要支持这种情况。此时数组中的第一个数字就是最小的数字,可直接返回。
分析:
仔细分析下标index1和index2(对应P1和P2)当这两个数字和中间数字都相同时,如图。
例
数组{1,0,1,1}和{1,1,1,0,1}都可以看成递增排序数组{0,1,1,1,1}的旋转。
这两种情况,第一个指针和第二个指针的数字都是1,并且两个指针中间的数字也是1,这三个数字相同,无法判断中间数字是位于前面数组还是后面数组,无法移动指针缩小范围,不得不采用顺序查找的方法。
实现
package ti11;
//题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
//输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组
//{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。
public class MinNumberInRotatedArray {
public int minNumberInRotateArray(int[] array) {
if (array == null || array.length <= 0) // 空数组或null时返回0
return 0;
int low = 0;
int high = array.length - 1;
int mid = (low + high) / 2;
//升序数组
if (array[low] < array[high])
return array[low];
//中间数字与首尾数字相等
if (array[mid] == array[high] && array[mid] == array[low]) {
for (int i = 1; i <= high; i++) {
if (array[i] < array[i - 1])
return array[i];
}
return array[low];
}
//正常情况
while (low < high) {
if (high - low == 1)
break;
mid = (low + high) / 2;
if (array[mid] <= array[high])
high = mid;
if (array[mid] > array[high])
low = mid;
}
return array[high]; // 别错写成了return high; !!
}
// =======测试代码======
public void test1() {
int[] array = null;
System.out.println("test1:" + minNumberInRotateArray(array));
}
public void test2() {
int[] array = {};
System.out.println("test2:" + minNumberInRotateArray(array));
}
public void test3() {
int[] array = { 1 };
System.out.println("test3:" + minNumberInRotateArray(array));
}
public void test4() {
int[] array = { 1, 2, 3, 4, 5, 6 };
System.out.println("test4:" + minNumberInRotateArray(array));
}
public void test5() {
int[] array = { 2, 2, 2, 2, 1, 2 };
System.out.println("test5:" + minNumberInRotateArray(array));
}
public void test6() {
int[] array = { 2, 1, 2, 2, 2, 2 };
System.out.println("test6:" + minNumberInRotateArray(array));
}
public void test7() {
int[] array = { 6, 6, 8, 9, 10, 1, 2, 2, 3, 3, 4, 5, 6 };
System.out.println("test7:" + minNumberInRotateArray(array));
}
public static void main(String[] args) {
MinNumberInRotatedArray demo = new MinNumberInRotatedArray();
demo.test1();
demo.test2();
demo.test3();
demo.test4();
demo.test5();
demo.test6();
demo.test7();
}
}
参考:
1.《剑指offer》
2.https://www.cnblogs.com/yongh/p/9649169.html