【剑指Offer记录】11_旋转数组的最小数字

本文介绍了在保证时间复杂度为O(logn)的前提下,如何使用二分法在旋转数组中找到最小值。文章详细讨论了常规情况、特殊情况1(如[10111])和特殊情况2(如[122222]),以及与书中学到的其他方法的对比和优化点。
摘要由CSDN通过智能技术生成

Part1. 我的思路和代码

一般情况:

要求的时间复杂度为O(logn),通过遍历一遍数组来找到最小值的时间复杂度为O(n),不满足此要求。由旋转数组的定义可知,数组由两段排好序的部分组成,结合时间复杂度为O(logn),想到二分法。分析旋转数组的特点,发现搬到数组末尾那段元素的最后一个元素,不会大于旋转后数组的首元素,用图表示如下:

在这里插入图片描述

原来数组为非降序(左边),以divider为界变为旋转数组(右边),新的数组出现了一个类似“断崖”的“非升序”部分,即图右边红色虚线的位置,该位置的元素(原来的end)和旋转数组的第一个元素A依然保持非降序关系,但和最后一个元素B不满足非降序关系(一般情况是这样,后文有特殊情况),因此通过二分法不断地寻找“断崖”的位置,从断崖处的两个元素找到较小的即为所求

具体做法上,先计算旋转数组的中间位置middle,接着比较middle位置的元素同A和B的关系,如果和A不满足非降序关系,那么“断崖”位于区间[A, middle](闭区间,下同),如果和B不满足则位于区间[middle, B],在新的区间继续同样的过程,直到新区间只有两个元素,最后返回两个元素的较小值。

采用二分思想,时间复杂度为O(logn)。

特殊情况1:

上述做法下,输入为[1 0 1 1 1]时无法通过,因为middle为1,和最左元素A、最右元素B比较时,发现都满足非降序关系。该情况下,不可以将middle随机变为其他值,因为仍然有可能出现同样的情况,只能从A的下一个元素开始到B的上一个元素为止,逐个寻找“特殊的middle”位置,使该位置或者和A不满足非降序关系,异或和B不满足非降序关系。

特殊情况2:

加上特殊情况1的处理,输入为[1 2 2 2 2 2]时无法通过,此种情况属于旋转数组和原数组相同的情况,在特殊情况1中,对应找不到“特殊的middle”位置的情况,此时说明数组已经是非降序排列的,最小元素就是A。

int minNumberInRotateArray(vector<int>& nums) {
    int start;
    int end;
    int middle;
    int ans;

    start = 0;
    end = nums.size() - 1;
    while(end-start > 1){
        middle = (start+end)/2;
        if(nums[start]<=nums[middle] && nums[middle]<=nums[end]){ //特殊情况1
            int specialIdx = -1;
            for(int i=start+1; i<end; i++){
                if(!(nums[start]<=nums[i] && nums[i]<=nums[end])){
                    specialIdx = i;
                    break;
                }
            }
            if(specialIdx == -1){ //特殊情况2
                ans = nums[0];
                return ans;
            }
            middle = specialIdx;
        }
        if(nums[start]<=nums[middle]){ //一般情况或特殊情况1的后续
            start = middle;
        }
        else{ //一般情况或特殊情况1的后续
            end = middle;
        }
    }
    ans = nums[start]<nums[end] ? nums[start] : nums[end];

    return ans;
}

Part2. 其他做法

书中的方法

书中在表述上是“中间元素位于前面的递增子数组”和“中间元素位于后面的递增子数组”等方式,本质上我的思路和该方法应该是相同的。与书中的做法相比,发现我的方法有一个可以优化的地方:当找到“断崖”的位置时,其实不必比较两个元素的大小关系,右边元素一定是不大于左边元素的,也就是直接返回右边元素即可。

Part3. 心得体会

  • 再次体会到题目难易是相对的,即使标注着是简单题,思维没有到位依然很难。这道题对我来说是一道“并不简单的简单题”。
  • 特殊情况的处理很考验思维的严谨性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值