6.旋转数组的最小数字
三种方法,(题目的意思是输出整个数组的最小值。其中是一个非减排序。。说明:最小值位置是出现单调性改变
)
1、最笨的一种:
遍历整个数组,找出其中最小的数。这样肯定拿不到offer
2、稍微优化:时间复杂度O(n)
first-数组为空,返回0
second-一般情况部分旋转,例如由(1,2,3,4,5)旋转为(3,4,5,1,2),此时只需要遍历数组,找到当前数比前面的数小的数即可。
third-特殊情况需要完全旋转也就是没有旋转,例如由(1,2,3,4,5)旋转为(1,2,3,4,5),此时第一个数最小。返回array[0].
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
//数组为空时
if(array.length==0) return 0;
//前部分数据旋转
for(int i=0;i<array.length-1;i++){
if(array[i]>array[i+1])
return array[i+1];
}
//全部数据旋转,相当于没有旋转,最小数即为第一个数
return array[0];
}
}
import java.util.ArrayList;
public class Solution {//输出旋转数组的最小元素
public int minNumberInRotateArray(int [] array) {
if(array.length==0)
return 0;
int min=array[0];
for(int i=1;i<array.length;i++){
if(min>array[i]){
min=array[i];
break;
}
}
return min;
}
}
以上这种完全忽略了旋转数组。其次数组有序的话应该考虑二分法
3、二分查找:时间复杂度为O(log(n))
查找时分三种情况:
1、array[mid] > array[high]:说明旋转后最小值在右区间,左边界设置low = mid + 1
2、array[mid] =array[high]:出现这种情况的array类似 [1,0,1,1,1] 或者[1,1,1,0,1],此时最小数字不好判断在mid左边还是右边,这时只好一个一个试 ,high = high - 1
3、array[mid] <array[high]:出现这种情况的array类似[2,2,3,4,5,6,6],此时最小数字一定就是array[mid]或者在mid的左边。因为右边必然都是递增的。 high = mid
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
int low = 0 ;
int high = array.length - 1;
while(low < high){
int mid = low + (high - low) / 2;
//如果中间值大于最后值,那么说明乱序的部分在后半段,所以在后半段寻找。可以使用mid+1是因为,中间值都比最后值大了,那还要它干嘛?
if(array[mid] > array[high]){
low = mid + 1;
}else if(array[mid] == array[high]){
// 如果array=[1,0,1,1,1]或者[1,1,1,0,1],那没办法判断乱序子数组的位置,所以只能削减一步
high = high - 1;
}else{
//如果中间值小于最后的值,说明后半部分为非减序列,所以在前半部分继续寻找;
high = mid;
}
}
return array[low];
}
}
二刷的问题:二分查找思路没有想到,直接都是使用了第二种方法。二分查找需要更加的熟悉。
中间值也可以表示为mid=(low+high)/2;
mid=low+(high-low)/2
返回值的时候可以直接return array[high];