旋转数组的最小数字
剑指offer第11道题:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
刚开始读题,一遍都没读懂(我是小白,才开始入门),再读一遍,题目的目的不就是求出一个在一个数组中的最小值,如果数组大小为0,则返回0
第一次思路:
于是我就一下子想用暴力来解决这道题,遍历这个数组,用一个指针来指最小值,每次如果比这个指针的值小就更新为最小,直到遍历完整个数组得到最小值,不用说时间复杂度是0(n)
再一想这道题也没有这么简单,再读读题目,发现题目中的非递减排序的数组,有这么个条件我们没有用到,我们来看example:
对于数组3,4,5,1,2,这个数组是由两个子数组345和12交换位置得来的,原数组12345,又发现交换后,前面的数组中的值都比后面的数组中的值小,而我们要找的这数字肯定在这两个数组交界处,所以没有可能必要遍历完整个数组,当然存在其他情况,稍后补充
第二次思路:
我们通过二分思想来解决这道题
在数组中定义两个指针下标l和r,同时定义一个mid下标指针,这个指针用来缩小l和r的范围,从而确定出最小值
对于这个数组,如果mid下标指的值比r下标指的值大,说明mid在左边的数组中,进一步我们挪动l到mid处,下一次新的l到r遍历范围缩小
如果mid下标的值比l下标的值小,说明mid在右边的数组中,在这个栗子中,5比3大说明,在345这个数组中
不断的缩小遍历范围,我们最终找到那个最小值,代码思路如下:
public class Solution {
public int minNumberInRotateArray(int array[]){
if(array.length==0){
return 0;
}
int l=0;
int r=array.length-1;
while(l<r-1){
int mid=(l+r)>>1;
if(array[mid]>=array[l]){//如果中间的值大于左边的值,说明mid的下标在第一个左子数组上
l=mid;
}else if(array[mid]<=array[r]){//如果中间的值小于右边的值,说明mid的下标在右边的子数组上
r=mid;
}
}
return array[r];
}
}
时间复杂度是0(logn)
为什么这里的比较条件是array[mid]>=array[l],没有等号行吗,如果没有等号对于3,2,2,2,2,这样的栗子,while循环就一直出不去