题目链接:旋转数组的最小数字
题意:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
题解:很容易想到的是o(n)的算法。但是不能忽略它旋转数组的性质。数组划分成两段,且都是有序的。可以优化到o(logn)
设中间的数为mid,最左边的数为left,最右边的数为right,很容易得到三种情况,设最小的数为numer.
- array[mid] < array[right] 此时numer在[left,mid],right = mid
- array[mid] > array[right] 此时number在[mid+1,right],left = mid+1
- array[mid] = array[right] 此时不能确定是否在有序范围内,所以只能顺序查找,让right-1
因为二分的范围会到只剩下两个的情况,而我们只是在用mid和right做比较。所以在第一种情况不能直接right=mid-1.
代码:
1 O(n) 2 import java.util.ArrayList; 3 public class Solution { 4 public int minNumberInRotateArray(int [] array) { 5 int len = array.length; 6 if(len == 0){ 7 return 0; 8 } 9 else{ 10 int num = array[0]; 11 for(int i = 0 ;i < len;i++){ 12 if(num > array[i]){ 13 num = array[i]; 14 } 15 } 16 return num; 17 } 18 } 19 } 20 21 22 OR 23 24 O(logn) 25 import java.util.ArrayList; 26 public class Solution { 27 public int minNumberInRotateArray(int [] array) { 28 int len = array.length; 29 if(len == 0){ 30 return 0; 31 } 32 else{ 33 int left = 0; 34 int right = len-1; 35 int mid,num; 36 37 while(left < right){ 38 mid = (left + right)/2; 39 if( array[mid] < array[right]){ 40 right = mid; 41 } 42 else if(array[mid] > array[right]){ 43 left = mid+1; 44 } 45 else{ 46 right--; 47 } 48 } 49 num = array[left]; 50 51 return num; 52 } 53 } 54 }