寻找旋转排序数组中的最小值

前言

记录一下刷题历程 力扣第153题寻找旋转排序数组中的最小值


寻找旋转排序数组中的最小值

原题目:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
示例 2:

输入:nums = [4,5,6,7,0,1,2]
输出:0
解释:原数组为 [0,1,2,4,5,6,7] ,旋转 3 次得到输入数组。
示例 3:

输入:nums = [11,13,15,17]
输出:11
解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。

分析

原来的一个有序数组,我们只需要返回数组最左侧的元素即可。加入原数组为[1,2,3,4,5]当我们经过一次旋转后数组变为[4,5,1,2,3],根据图像我们可以知道这是两条递增的直线,对于这个例子我们只需要找到第二条直线也就是[1,2,3]返回它的最左边的元素即可。那应该如何找到呢?第一中情况:如果左指针元素小于等于中间元素且中间元素小于等于右指针元素,说明数组已经是升序排列,直接返回左指针元素。第二种情况如果中间元素大于等于左指针元素,说明最小值在右半部分,更新左指针为中间指针的下一个位置。第三种情况:如果中间元素小于等于右指针元素,说明最小值在左半部分或者当前中间元素就是最小值,更新右指针为中间指针

代码如下:

class Solution {
public:
    int findMin(vector<int>& nums) {
        // 初始化左右指针和中间指针
        int left = 0;
        int right = nums.size() - 1;
        int mid = 0;
        
        // 使用二分查找法来寻找最小值
        while (left <= right) {
            mid = (left + right) / 2; // 计算中间指针的位置
            
            // 情况1:如果左指针元素小于等于中间元素且中间元素小于等于右指针元素,说明数组已经是升序排列,直接返回左指针元素
            if (nums[left] <= nums[mid] && nums[mid] <= nums[right]) {
                return nums[left];
            } 
            // 情况2:如果中间元素大于等于左指针元素,说明最小值在右半部分,更新左指针为中间指针的下一个位置
            else if (nums[mid] >= nums[left]) {
                left = mid + 1;
            } 
            // 情况3:如果中间元素小于等于右指针元素,说明最小值在左半部分或者当前中间元素就是最小值,更新右指针为中间指针
            else if (nums[mid] <= nums[right]) {
                right = mid;
            }
        }
        
        // 如果循环结束仍未找到最小值(理论上不会发生),返回-1
        return -1;
    }
};

解释注释

三种情况判断:

情况1:升序情况:

nums[left] <= nums[mid] && nums[mid] <= nums[right]:如果左指针元素小于等于中间元素且中间元素小于等于右指针元素,说明数组已经是升序排列,直接返回左指针元素 nums[left]。

情况2:右半部分有序:

nums[mid] >= nums[left]:如果中间元素大于等于左指针元素,说明最小值在右半部分,更新左指针为中间指针的下一个位置 left = mid + 1。

情况3:左半部分有序或中间元素是最小值:

nums[mid] <= nums[right]:如果中间元素小于等于右指针元素,说明最小值在左半部分或者当前中间元素就是最小值,更新右指针为中间指针 right = mid。

时间复杂度

这个方法的时间复杂度是 O(log n),其中 n 是数组 nums 的大小。因为二分查找每次将搜索范围缩小一半,所以总体时间复杂度是对数级别的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值