题目:(来自《剑指offer》)
输入一个递增数组的旋转数组,找出数组中最小的数字。例如 数组 {3,4,5,1,2} 是递增数组{1,2,3,4,5} 的一个旋转数组,其中最小的数字是 1 。
思路:
最简单的思路是 遍历数组,这样就能找出最小的数字,时间复杂度为 O(n),代码简单,此处不写。
但是这样我们就没有用到题目给的 递增 旋转数组的性质,怎么用上呢?因为它是递增数组的旋转数组,所以实际上它可以分成两部分,这两部分都为 递增,且后面部分的任意数字都比前面的任意数小,比如{3,4,5,1,2} 可以分为
:{3,4,5} 和 {1,2} ,这样我们可以设置两个指针,分别指向第一个数字跟第二个数字,然后求出中间位置的数字:
arr[mid] ,如果arr[mid] 大于arr[low],那么证明arr[mid] 属于前部分数组,则最小数在 mid 后面,令 low = mid ,
如果 arr[mid] 小于 arr[low] 证明arr[mid] 再后面部分 数组中 ,最小值在 mid 前面(也可能为arr[mid]),
令height = mid.最后可以得出arr[height] 为数组中最小的数字。
具体代码如下:
/**
* 输入一个递增数组的旋转数组,输出数组中最小的数字
* 例如 数组{3,4,5,1,2} 是 {1,2,3,4,5} 的旋转数组,最小元素是 1
* @author luzi
*
*/
public class minNumofReverseArr {
public static void main(String args[]){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int[] arr = new int[n];
for(int i = 0;i < n;i++){
arr[i] = scan.nextInt();
}
System.out.println(getMinNum(arr));
}
public static int getMinNum(int[] arr){
if(arr == null || arr.length <1)
return -1;
if(arr.length <= 2)
return arr[arr.length - 1];
int low = 0;
int height = arr.length - 1;
while(height - low > 1){
int mid = (height + low)/2;
if(arr[mid] >= arr[0])
low = mid;
else
height = mid;
}
return arr[height];
}
}