一、题目描述
JZ6旋转数组的最小数字
题目大意:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
注意审题:给出的所有元素都大于0,若数组大小为0,请返回0
二、算法1(暴力遍历)
算法思路
总体思想:遍历一遍数组并不断更新最小值即可,可以拿第一个元素作为初始的最小值
代码实现(C++11)
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if(rotateArray.empty()) return 0; int ans = rotateArray[0]; for(int& x : rotateArray){ ans = min(ans, x); } return ans; } };
时间复杂度:O(n)
空间复杂度:O(1)
三、算法2(二分法)
算法思路
1.总体思路:由于原数组是非递减的,因此我们联想到是否可以用二分法解决,由于旋转后最多有两段非递减的序列,因此我们可以使用二分法来寻找最小值
2.根据二分法的步骤,我们可以根据中间值的大小来确定区间的缩小,就本题来说,我们可以通过与右指针所指的值相比来作为划分的依据,由于可能存在重复的值,因此可能出现mid所指的值与右指针所指的值相同的情况,此时我们只能将右指针向右移动;当mid所指的值小于右指针r所指的值时,就将右指针移动至mid处,区间缩短为[l,mid];当mid所指的值大于右指针r所指的值时,将左指针移动至mid + 1处即可,此算法的平均时间复杂度是O(logn)
3.由于可能存在重复的值,因此最坏的情况下整个数组的值都相同,此时要不断的移动右指针,时间复杂度退化至O(n)
代码实现 (C++11)
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if(rotateArray.empty()) return 0; int l = 0, r = rotateArray.size() - 1; while(l < r){ int mid = l + r >> 1; if(rotateArray[mid] < rotateArray[r]) r = mid; else if(rotateArray[mid] > rotateArray[r]) l = mid + 1; else --r; } return rotateArray[l]; } };
时间复杂度:平均时间复杂度O(logn), 最坏时间复杂度O(n)
空间复杂度:O(1)