题意思路:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
方法一:暴力枚举
通过遍历数组求出最小的元素
复杂度分析
时间复杂度:O(N),N数组的长度,遍历数组;
空间复杂度:O(1),未开辟新空间
代码:
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { int res=INT_MAX; for( auto i : rotateArray){ res=min(res,i); } return res; } };
方法二:二分法
可以将这个旋转的数组看作是前后两个有序的子数组, 设置指针mid = (l + r) / 2.
1.当选取的中间值 mid 所对应的值大于 l 所对应的值时,说明此时 mid 还在第一有序的数组中,而我们所要求解的最小值是在第二个有序数组的第一个位置,此时也就是在 mid 的后面,我们就将 l 移到 mid 所在的位置.
2.当 r 所对应的值大于 mid 所对应的值时,说明最小值可能是 mid 所对应的值或者在 mid 的前面,我们将 r移到 mid 所在的位置.
3.若r所对应的值等于mid所对应的值时,此时减少区间缩小范围。
最后 l 所在的位置就是最小值的位置,直接返回即可.
图解:
复杂度分析
时间复杂度:O(logN),N数组的长度,二分遍历数组;
空间复杂度:O(1),未开辟新空间
代码:
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if (rotateArray.size() == 0) return 0; int l = 0, r = rotateArray.size() - 1; while (l < r) { // 当左指针小于右指针满足条件 if (rotateArray[l] < rotateArray[r]) { // 得到最小值 return rotateArray[l]; } int mid = l + r>> 1;//得到中间指针 比较大小 if (rotateArray[mid] > rotateArray[r]) { // l = mid + 1; //原始数组是非递减,所以可以确定答案为 [mid+1...r]区间,所以 l = mid + 1 } else if (rotateArray[mid] < rotateArray[r]) { //情况2 r = mid; } //说明答案肯定不在[mid+1...r],但是arr[mid] 有可能是答案,所以答案在[l, mid]区间,所以r = mid; else { // 当rotateArray[mid] == rotateArray[r]时只能减少区间 --r; } } return rotateArray[l]; } };