剑指offer——11旋转数组中最小的数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
第一种方法:
从头开始遍历,当遇到不满足非递减排序规律的那个数时,那就是旋转的边界数,然后将其与最左端的数比较,得到最小的数
第二种方法:
二分法【貌似测试的时间和空间复杂度都更大】
使用三个指针,左指针,右指针,中间指针;
第一个指针总是指向前面递增数组的元素,而第二个指针总是指向后面递增数组的元素。
最终第一个指针将指向前面子数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素。也就是它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素。这就是循环结束的条件。
但是,当两个指针指向的数字及它们中间的数字三者相同的时候,我们无法判断中间的数字是位于前面的子数组中还是后面的子数组中,也就无法移动两个指针来缩小查找的范围。此时,我们不得不采用顺序查找的方法。
1 class Solution01 { 2 public: 3 int minNumberInRotateArray(vector<int> rotateArray) { 4 if (rotateArray.size() == 0)return 0; 5 int minN = rotateArray[0]; 6 for (int i = 0; i < rotateArray.size() - 1; ++i) 7 if (rotateArray[i] > rotateArray[i + 1]) 8 return minN < rotateArray[i + 1] ? minN : rotateArray[i + 1]; 9 return minN; 10 } 11 }; 12 13 class Solution02 { 14 public: 15 int minNumberInRotateArray(vector<int> rotateArray) { 16 if (rotateArray.size() == 0)return 0; 17 int L = 0, R = (int)rotateArray.size() - 1, M = 0; 18 while (rotateArray[L] >= rotateArray[R]) 19 { 20 if (R - L == 1) 21 { 22 M = R; 23 break; 24 } 25 M = (L + R) / 2; 26 if (rotateArray[M] == rotateArray[L] && rotateArray[M] == rotateArray[R]) 27 return getMin(rotateArray, L, R); 28 else if (rotateArray[M] >= rotateArray[L]) 29 L = M; 30 else 31 R = M; 32 } 33 return rotateArray[M]; 34 } 35 36 int getMin(vector<int> Num, int L, int R) 37 { 38 int minN = Num[L]; 39 for (; L <= R; ++L)minN = minN < Num[L] ? minN : Num[L]; 40 return minN; 41 } 42 };
In the previous subarray. therefore,