题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
非递减是指后面的大于等于前面的,递增是指后面的大于前面的。123345和123456的区别
样例输入输出
输入
[3,4,5,1,2]
返回值
1
解答
该题为二分法的变种,没有target目标值
需要考虑以下三种情况
- array[mid] > array[high]:类似于456123,array[mid]=6,array[high]=3,最小值在array[mid]的右边,所以low=mid+1
- array[mid]<array[high]:类似于561234,array[mid]=1,array[high]=4,最小值可能为array[mid],或者再array[mid]的左边,所以high=mid
- array[mid]==array[high]:类似于10111或者11101,这种情况下不确定最小值是在array[mid]的左边还是右边,需要high=high-1一个一个试
import java.util.ArrayList;
public class Solution {
public int minNumberInRotateArray(int [] array) {
if(array.length == 0){
return 0;
}
int low = 0;
int high = array.length - 1;
while(low < high){//当low和high重合时返回
int mid = low + (high - low )/2;
if(array[mid] > array[high]){//第一种情况,如456123
low = mid + 1;
}else if(array[mid] < array[high]){//第二种情况,如561234
high = mid;
}else{//第三种情况,如10111,11101
high = high - 1;
}
}
return array[low];
}
}
思路分析
该题不同于以往的二分查找算法,没有给出target目标值,所以需要通过端点值进行比较,题目给出的数组为非递减排序的数组的一个旋转,所以比较会出现三种情况,根据三种情况进行low和high值的改变,再次进行比较,直到得出最小值返回。
二分(折半)查找算法
前提条件
数组有序
算法思想
取中间值再比较
- 通过low和high计算出mid,mid=low+(low+high)/2
- 将array[mid]和target目标值进行比较,会出现以下三种情况
1.array[mid] > target:说明target目标值位于array[mid]的左侧,则将high赋值为mid-1;
2.array[mid] < target:说明target目标值位于array[mid]的右侧,则将low赋值为mid+1;
3.array[mid] == target:直接返回mid
代码实现
//二分查找算法
public static int binarySearch(int[] arr,int target){
int high = arr.length - 1;
int low = 0;
while(low <= high){
int mid = low + (high-low)/2;//该写法可以防止溢出
if(arr[mid] < target ){//target目标值位于array[mid]的右侧
low = mid +1;
}else if(arr[mid] > target ){//target目标值位于array[mid]的左侧
high = mid - 1;
}else{
return mid;
}
}
return -1;
}