一:主题
1.题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
2.思路
在最开始,我看到这个题目,以为就是使用遍历,然后百度了一下,原来里面还有玄机。
首先,就是考虑的是时间复杂度,重要的特性就是人家为啥弄一个旋转数组,要考虑。
和二分查找一样,我们left和right分别指向数组的第一个元素和最后一个元素。
如果中间元素大于第一个元素,那么最小值应该在后一部分,我们left = mid
。如果中间元素小于最后一个元素,那么最小值应该在前一部分,我们right = mid
。以此查找最小元素。
注意:需要注意一种特殊的情况是,原本的排序就是有序的。我们令初始的中间指针mid指向第一个元素。
另外还有一种情况就是,当三个指针 right
, left
和 mid
均相同时,如下图所示,我们无法断定前后那一部分包含最小值,此时只能用顺序查找算法。
3.程序
这里使用两种方式。
1 package first; 2 3 /** 4 * 旋转数组中的最小数 5 */ 6 public class MinNumberInRotateArray { 7 8 public static void main(String[] args){ 9 int[] num={3,4,5,1,2}; 10 //方式一 11 int minNum=getNum(num); 12 System.out.println("==="+minNum); 13 //方式二 14 int minNum2=getNum(num); 15 System.out.println("==="+minNum2); 16 } 17 18 /** 19 * 直接进行比遍历,然后时间复杂度是n 20 */ 21 public static int getNum(int[] num){ 22 int j=0; 23 for(int i=0;i<num.length-1;i++){ 24 if(num[i]>num[i+1]){ 25 j=i+1; 26 break; 27 } 28 } 29 return num[j]; 30 } 31 32 /** 33 * 使用二分查找的方式,时间复杂度更小 34 */ 35 public static int getNum2(int[] array){ 36 // 如果数组长度为0则返回-1 37 if (array.length == 0) 38 { 39 return -1; 40 } 41 int left = 0; 42 int right = array.length - 1; 43 int mid = left; 44 // 当最左边值大于等于最右边时候 45 while (array[left] >= array[right]) 46 { 47 // 如果此时数组只剩下两个数值 48 if (right - left == 1) 49 { 50 // 最小的就是右边 51 mid = right; 52 break; 53 } 54 // 如果数组长度是2个以上 55 mid = (left + right) / 2; 56 // 假如最左边和中间以及最右边值都相等,只能进行顺序查找,如{1,1,1,0,1} 57 if (array[left] == array[mid] && array[left] == array[right]) 58 return orderFind(array, left, right); 59 // 如果最左边小于等于中间,说明最小值在后半部分,把mid位置标记为最左侧如{3,4,5,1,2} 60 if (array[mid] >= array[left]) 61 left = mid; 62 // 如果最左侧大于等于中间值,说明最小值在前半部分,把mid位置标记为最右侧{4,5,1,2,3} 63 else if (array[mid] <= array[left]) 64 right = mid; 65 } 66 return array[mid]; 67 } 68 69 public static int orderFind(int[] array, int left, int right) 70 { 71 int min = array[left]; 72 for (int i = left + 1; i <= right; i++) 73 { 74 if (array[i] < array[left]) 75 min = array[i]; 76 } 77 return min; 78 } 79 80 }
4.时间复杂度
直接遍历时间复杂度:O(n)
二分查找的时间复杂度更小:O(log2n)
5.参考