一、题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
二、思路分析:
我自己的思路是这样的,先把这个旋转数组的各种情况都考虑全面,if-else 分开,然后再对每种情况展开讨论,得出除了特殊情况外可以用算法复杂度较低的二分法来求。但是某有两个特殊情况必须用暴力顺序查找了。
情况分类:
(1):输入的旋转数组的大小为0时
(2): 该旋转数组是前0个元素放到了末尾的情况
(3):容易忽略的条件
非递减数组的旋转的意识是 可以是数字连续的比如:12222 旋转为:22212 或者旋转为:212222
这种情况就是容易忽略的情况,这种情况无法用二分法来计算,因为不知道mid值是左边半个数组还是右边半个数组的,只能用暴力法求解。
(4):正常情况,用二分法
三、可运行java代码
public class Solution_6 {
public int minNumberInRotateArray(int[] array) {
if (array.length == 0) { // 输入的旋转数组的大小为0时
return 0;
}
int i = 0, j = array.length - 1, mid = (i + j) / 2;
if (array[1] < array[array.length - 1]) { // 该旋转数组是前0个元素放到了末尾的情况
return array[1];
}
// 容易忽略的条件
// 非递减数组的旋转的意识是 可以是数字连续的比如:12222 旋转为:22212 或者旋转为:212222
// 这种情况就是容易忽略的情况,这种情况无法用二分法来计算,因为不知道mid值是左边半个数组还是右边半个数组的,只能用暴力法求解
if (array[mid] == array[i] && array[mid] == array[j]) {
return findMin(array); // 调用暴力求解发,求出最小值
}
// 剩下的情况都可以用二分法来求解
while (i < j - 1) { // 由于下面mid采用的是向下取整,所以这里是i<j-1即可,否则i<j会先入死循环
if (array[i] <= array[mid]) {
System.out.println("i=" + i + ";j=" + j);
i = mid;
mid = (i + j) / 2;
} else {
j = mid;
mid = (i + j) / 2;
}
}
System.out.println("mid=" + mid);
return array[mid + 1];
}
// 暴力法:顺序查找
public int findMin(int[] array) {
int min = array[1]; // 假设数组第一个值为最小值
for (int i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
//测试例子
public static void main(String[] args) {
int[] a = { 6501, 6828, 6963, 7036, 7422, 7674, 8146, 8468, 8704, 8717,
9170, 9359, 9719, 9895, 9896, 9913, 9962, 154, 293, 334, 492,
1323, 1479, 1539, 1727, 1870, 1943, 2383, 2392, 2996, 3282,
3812, 3903, 4465, 4605, 4665, 4772, 4828, 5142, 5437, 5448,
5668, 5706, 5725, 6300, 6335 };
Solution_6 s = new Solution_6();
System.out.println(s.minNumberInRotateArray(a));
}
}