题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
题目关键词:递增排序、旋转。
分析:上图是符合题目要求的三种数组,第一种是很正规的一种情况:数组因为旋转的原因,分成两个递增数组,而最小值位于后面数组的第一个值。针对此题,首先要想到的是采用二分查找,第二点非常重要的一点就是想到旋转数组条件特殊的数组,加以处理。(一个好的开发人员应该要是一个好的测试人员)
上图2是一个排好序的数组,是一种特殊的旋转数组,对于此种情况,直接返回数组的第一个元素即可,代码中体现为mid的初始值为start;上图三如果start、end、mid对应的值相等的情况二分无法确定最小值在哪部分,此时可以采用顺序查找。
package com.example;
public class FindMin {
public static void main(String[] args) {
int[] nums={6,7,8,1,2,3,4,5};//{1,0,1,1,1};//{1,2,3,4,5,6,7,8};//{3,4,5,1,2};
int minNUm=findMin(nums);
System.out.println("数组中最小的数"+minNUm);
}
/**
* 查找数组中的最小值
* @param nums 递增排序的旋转数组
* @return 数组中的最小值
*/
public static int findMin(int[] nums){
//判空处理
if(nums==null||nums.length<0){
throw new IllegalArgumentException("输入数组参数非法");
}
int start=0;//开始指针
int end=nums.length-1;//结束指针
int mid=start; //如果数组本来就是排好序的,则数组的第一个元素就是数组的最小值
while(nums[start]>=nums[end]){
if(end-start==1){//循环结束条件
mid=end;
break;
}
mid=(start+end)/2;
//如果start,end,mid指向的数组相等,则只能是采用顺序查找
if(nums[start]==nums[end]&&nums[start]==nums[mid]){
return minInOrder(nums,start,end);
}
if(nums[start]<=nums[mid]){
start=mid;
}else if(nums[end]>=nums[mid]){
end=mid;
}
}
return nums[mid];
}
private static int minInOrder(int[] nums, int start, int end) {
int result=nums[start];
for(int i=start+1;i<=end;i++){
if(result>nums[i]){
result=nums[i];
}
}
return result;
}
}