旋转数组的最小值

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{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}, 这也就是说, 最为简单直接的就是暴搜, 遍历数组, 当后一个值小于前一个值时, 后一个值就是最小值, 时间复杂度为O(N)

由于数组可以看作是两段有序的序列, 因此可以采用二分, 复杂度为O(logN)
举例来看二分的具体操作

在这里插入图片描述
一个别旋转过的数组可以看做两段有序的序列
分为
3, 4, 5 和 1, 2
此时我们需要寻找的是数组中的最小值, 也就是右半序列的第一个值
首先将a[left]与a[mid]比较, 如果 a[left] < a[mid], 这说明mid仍然处于左半部分递增序列当中, 也就是说, 数组最小值处于区间 [mid + 1, right]之间, 因此 此时修改 left = mid + 1;

在这里插入图片描述
同理, 接下来比较 a[right] 与 a[mid], 如果 a[mid] < a[right], 这说明数组最小值处于区间[left, mid], 也就是更新 right = mid;
注意 mid 不需要减 1, 可以想一下, 假如 mid 正好处于数组最小值的位置, 这时满足 a[mid] < a[right], 接下来更新right的值为 mid - 1, 这样接下来的搜索范围区间就变成了[left, mid - 1], 就错过了最小值.

上面所举例子, 更新 left 的值之后, a[mid] > a[right], 因此不需要更新 right的值

更新mid的值, mid = (left + right) / 2;

在这里插入图片描述
此时, 不满足 a[mid] > a[left], 不更新 left 的值
满足, a[mid] < a[right], 更新 right = mid;
在这里插入图片描述
此时 left = right, 跳出循环, 返回 a[left];

当然此时还并不完整, 因为题目给出的是 非递减序列, 比如这样一种特殊情况

1, 0, 1, 1, 1, 1
在这里插入图片描述
此时就会发现, a[mid] > a[left] 不成立, 不需要更新left
a[mid] < a[right] 也不成立, 也不需要更新right, 这样程序陷入死循环, 因此, 在上面条件判断的基础上, 再加一个条件
当上面两种情况都不满足是, left++;
与此同时, 在更新 mid 之前, 我们判断 a[left] < a[right]是否成立, 成立则直接返回a[left];

代码示例:

class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        int n = rotateArray.size();
        if (n == 0)
            return 0;
        int left = 0, right = n - 1;

        while (left < right)
        {
            if (rotateArray[left] < rotateArray[right])
                return rotateArray[left];
            int mid = (left + right) >> 2;
            if (rotateArray[left] < rotateArray[mid])
                left = mid + 1;
            else if (rotateArray[right] > rotateArray[mid])
                right = mid;//防止mid处于递增序列部分的第一个值
            else
                left++;
        }
        return rotateArray[left];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值