题目描述:
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1≤n≤10000,数组中任意元素的值: 0≤val≤10000
要求:空间复杂度:O(1) ,时间复杂度:O(logn)
示例:
输入:
[3,4,5,1,2]
返回值:
1
解题思路:
本题考察算法-搜索算法的使用。二分查找思想,具体思路如下:
- 左右边界初始设在数组两端,二分法压缩搜索区域。
- 若中间值高于右边界值,考虑到旋转数组旋转前的升序特性,左边界值应该等于或大于右边界值,也就是说最小值是在中间值的右侧,因此将左边界设在中间+1的位置。
- 若中间值等于右边界值,很大概率中间值到右边界值的这段区域都是同一数值,因此我们将右边界左移后再尝试。
- 若中间值低于右边界值,毫无疑问,中间值到右边界值的过程是升序的,那最小值要么就是中间值,要么就在中间值左侧,因此将右边界设在中间值位置,继续查找。
测试代码:
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { // 确定左右边界 int left = 0; int right = rotateArray.size() - 1; // 二分查找 while(left < right) { int mid = (left + right) / 2; // 目标在右边 if(rotateArray[mid] > rotateArray[right]) left = mid + 1; // 无法判断,将右边界压缩再试 else if(rotateArray[mid] == rotateArray[right]) right--; // 最小数字要么是mid要么在mid左边 else right = mid; } return rotateArray[left]; } };