【Offer】[11] 【旋转数组的最小元素】
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路分析
利用二叉查找的思路,由于是旋转数组,可以分成两个排序的子数组,而且最小元素是这两个数组的分界线,设置两个索引指针分别指向首尾元素,判断它们与数组中间元素的大小关系:
- 如果中间元素>=第一个元素则说明要找的最小元素在中间元素的后面,将第一个指针指向中间元素;
- 如果中间元素<=最后一个元素则说明要找的最小元素在中间元素的前面,将第二个指针指向中间元素;
- 这样重复的缩小范围查找,最终第一个指针会指向前面子数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素,即两个指针会相邻,这是最小元素便为第二个指针所指的元素
特殊情况: 如果中间元素 、第一个指针指向元素 、第二个指针指向元素 都相等,这时就不能用二分查找的思路,可以用顺序查找思路进行查找最小值
Java代码
public class Offer011 {
public static void main(String[] args) {
// int [] arr = {3,4,5,1,2};
int [] arr = {1,0,1,1,1};
int minNumberInRotateArray = minNumberInRotateArray(arr);
System.out.println(minNumberInRotateArray);
}
public static int minNumberInRotateArray(int [] array) {
return Solution1(array);
}
/**
* 利用二分查找的思路,注意:要考虑特殊情况
* @param array
* @return
*/
public static int Solution1(int [] array) {
int index1 = 0;
int index2 = array.length-1;
int indexMid = index1;
while(array[index1]>=array[index2]) {
if(index2-index1==1) {
indexMid= index2;
break;
}
indexMid = (index1+index2) >>1;
if(array[index1] == array[index2] && array[indexMid] == array[index1]) {
//特殊情况:要用顺序查找
return MinInOrder(array, index1, index2);
}
if(array[indexMid]>=array[index1]) {
index1 = indexMid;
}else if(array[indexMid]<=array[index2]) {
index2 = indexMid;
}
}
return array[indexMid];
}
/**
* 在index1和index2之间顺序查找最小值
* @param array 在此数组中进行查找
* @param index1 开始索引位置
* @param index2 结束索引位置
* @return
*/
private static int MinInOrder(int[] array,int index1,int index2) {
int min = array[index1];
for(int i=index1+1;i<=index2;i++) {
if(min > array[i]) {
min = array[i];
}
}
return min;
}
}
代码链接
************ **供自己学习查阅使用(我只想静静的写篇博客,自我总结下[手动狗头]) by Pavel** *********