🐮客上剑指Offer题6,求解旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
示例
[3,4,5,6,1,2]就是非递减排序数组[1,2,3,4,5,6]的一个旋转数组,输出的是旋转数组[3,4,5,6,1,2]中的最小值。
解题思路一:
看到求一个数组中的最小值,立马想到排序啊,然后输出第一个元素啊,so easy啊!给出思路一代码:
public int minNumberInRotateArray1(int [] array) {
int len = array.length;
if(len == 0) {
return 0;
}
Arrays.sort(array);
return array[0];
}
寥寥几行代码,完事!但是,《剑指Offer》上的题大多是练习算法的,因此为了提高算法的技能点,进一步进行解题,下面给出解题思路二。
解题思路二:
题中给出旋转数组是由一个非递减数组变化得到的,因此可知旋转数组是部分非递减有序的(旋转拼接点处为划分点,将旋转数组划分为两个有序数组),既然有序,还是查找,那当然是二分啦!
那怎么实现呢?
下面给出非递减有序数组旋转变化的情况示意图:
有序非递减数组的旋转数组的走向可以为图上三种情况,因此可以通过判断二分过程中的array[mid]与左右相邻的值的大小来判断mid是否为连接点,如果不是再与array[0]比较,判断连接点在哪。为什么通过与array[0]比较就可以判断呢?
因为原数组是非递减有序,因此旋转变换后,必有array[last]<=array[0]
,同时假设t是连接处,[0,t-1]是非递减,[t,last]是非递减,因此通过比较array[mid]和array[0]就可以判断连接点在哪个部分了。
代码如下:
public int minNumberInRotateArray2(int [] array) {
int len = array.length;
if(len == 0) {
return 0;
}
if(len == 1 || array[len-1] > array[0]) {//长度为1或者没有旋转
return array[0];
}
int low = 0;
int high = len-1;
while(low <= high) {
int mid = (low+high)/2;
if(array[mid] > array[mid+1]) {//凹部分,下降
return array[mid+1];
}
if(array[mid-1] > array[mid]) {//凸部分,上升
return array[mid];
}
if(array[mid] > array[0]) {//划分左右
low = mid+1;
}else {
high = mid-1;
}
}
return 0;
}
好了,本人水平有限,如有错误和不足欢迎大家指正和指导!
我是菜鸡程序猿,菜鸡程序猿就是我!