剑指offer——旋转数组的最小数字
问题描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
思路分析
1.先判断数组是否为空,数组的元素是否大于零。
2.观察会发现旋转数组是由两个递增数组组成。{3,4,5,} {1,2}
3.举例说明一般的情况。
如:数组{3,4,5,1,2},两个指针,p1指向首元素,p2指向尾元素,p指向p1和p2的中间元素。
3 4 5 1 2
p1 p p2
将p和p1指向元素进行比较,(先和左边比较)
5>3,说明5位于第一个递增子数组,并且最小的数一定在它后面。
所以将p1移动到p的位置。
3 4 5 1 2
p1 p p2
此时的p,为更新后的p1和p2的中间元素。
将p和p2指向元素进行比较,(再和右边比较)
1<2,说明1位于第二个递增子数组,并且最小的数一定在它前面或者自己就是最小的数字。
所以将p2移动到p的位置。
3 4 5 1 2
p1 p2
此时,p1和p2相邻,则p2为最小的数字
4.举例说明特殊的情况。
如:数组{2,1,2,2,2},{2,2,2,1,2} 均为{1,2,2,2,2}的旋转
2 1 2 2 2 2 2 2 1 2
p1 p p2 p1 p p2
可以看出两个数组都是 p1=p=p2
因此无法判断,p位置元素出于第一个递增数列还是第二个。
上面左边情况中,p属于第二个子数组。上面右边情况中,p属于第一个子数组。
此时,采取顺序查找的方法,按着顺序依次判断。
代码
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array == null || array.length <= 0){
return -1;
}
int index1=0;
int index2=array.length-1;
int indexMid=index1;//此处把indexMid的值初始为index1是因为如果旋转的是0个元素,
// 则数组等于本身,则第一个元素就是要找的最小元素。
while(array[index1]>=array[index2]){
//两个指针相邻的情况
if(index2-index1==1){
indexMid=index2;
break;
}
indexMid=(index1+index2)/2;
//和左边比较
if(array[index1]<=array[indexMid]){
index1=indexMid;
}
//和右边比较
else if(array[index2]>=array[indexMid]){
index2=indexMid;
}
//特殊情况
if(array[index1]==array[index2]&&array[index1]==array[indexMid]){
return MinInOrder(array,index1,index2);
}
}
return array[indexMid];
}
private int MinInOrder(int array[],int index1,int index2) {
int result = array[index1];
for (int i = index1+1; i <= index2; i++) {
if (result > array[i]) {
result = array[i];
}
}
return result;
}
}