题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
分析
分析这个题目,其实不用看什么数组的旋转的描述,感觉上没有多少意义,实际要做的就是对这个数组{3,4,5,1,2}进行操作,找到最小的那个数,当然这里自然而然的会 想到如果数组中有相同的元素时应该在怎么办。稍后分析。
现在来分析数组中的元素没有重复元素时,第一想到的肯定是进行数组的遍历,找出最小的数,但是这没有意义。我们再考虑这个数组其实是两个有序数组的结合。 若要在有序数组中查找某个元素,一般采用二分查找。
而二分查找要满足以下条件: (1)必须采用顺序存储结构 (2)必须按关键字大小有序排列
他的原理是将数组分为三部分,依次是中值(所谓的中值就是数组中间位置的那个值)前,中值,中值后;将要查找的值和数组的中值进行比较, 若小于中值则在中值前 面找,若大于中值则在中值后面找,等于中值时直接返回。然后依次是一个递归过程,将前半部分或者后半部分继续分解为三部分。
二分查找一般是要输入(作为参数)一个查找的值去匹配,而本题中,这个值是不定的,是需要寻找的,也就是数组的最小值。 我们首先把left指向数组的开头,而right指向数组的结尾,数组中包含两个非降序数组,有以下几种情况: (1)array[mid] > array[right];这个时候,那么array[mid]一定在前一个升序的子数组。最小的数一定在后面的数组中,所以将left指向mid+1。 (2)array[mid] == array[right].这个时候就要思考清楚了,加入有数组{1,1,1,1,1,0,1};原题中规定数组非降序,就只有升序和相等情况,相等的情况,不符合二分查找的要求,就要一个个的遍历数组进行求解,也就是将right每次都减小1; (3)array[mid] < array[right],这个时候最小的数,一定在前面的数组中。
代码
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if (array == null || array.length == 0) {
return 0;
}
int left = 0;
int right = array.length - 1;
while(left < right){
int mid = (left + right) /2;
if (array[mid] > array[right]) {
left = mid + 1;
}else if (array[mid] < array[right]) {
right = mid;
}else {
right--;
}
}
return array[left];
}
}