剑指offer(C++)-JZ11:旋转数组的最小数字(算法-搜索算法)

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

有一个长度为 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. 左右边界初始设在数组两端,二分法压缩搜索区域。
  2. 若中间值高于右边界值,考虑到旋转数组旋转前的升序特性,左边界值应该等于或大于右边界值,也就是说最小值是在中间值的右侧,因此将左边界设在中间+1的位置。
  3. 若中间值等于右边界值,很大概率中间值到右边界值的这段区域都是同一数值,因此我们将右边界左移后再尝试。
  4. 若中间值低于右边界值,毫无疑问,中间值到右边界值的过程是升序的,那最小值要么就是中间值,要么就在中间值左侧,因此将右边界设在中间值位置,继续查找。

测试代码:

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];
    }
};

猜你喜欢

转载自blog.csdn.net/zhaitianbao/article/details/126655346