剑指 Offer 11. 旋转数组的最小数字(简单题)

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

示例 1: 输入:[3,4,5,1,2] 输出:1
示例 2: 输入:[2,2,2,0,1] 输出:0

题解

单次遍历

由于原数组元素递增排序, 遍历时遇到后面一个元素值比前一个元素值小,则该元素值为数组最小元素; 如一直递增, 则返回初始元素。

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int n = numbers.size();
        for (int i = 0; i + 1 < n; i++) {
            if (numbers[i] > numbers[i+1]) {
                return numbers[i+1];
            }
        }
        return numbers[0];

    }
};

二分查找

算法流程

  • 初始化: 声明 ij双指针分别指向 nums 数组左右两端;
  • 循环二分: 设 m=(i+j)/2为每次二分的中点( “/” 代表向下取整除法,因此恒有 i≤m<j),可分为以下三种情况:
    1. 当 nums[m]>nums[j]时: m一定在 左排序数组 中,即旋转点 x一定在[m+1,j] 闭区间内,因此执行 i=m+1;
    2. 当 nums[m]<nums[j]时: m一定在 右排序数组 中,即旋转点 x一定在[i,m] 闭区间内,因此执行 j=m;
    3. 当 nums[m]=nums[j]时: 无法判断 m在哪个排序数组中,即无法判断旋转点 x在 [i,m]还是 [m+1,j] 区间中。解决方案: 执行 j=j−1缩小判断范围。
  • 返回值: 当 i=j时跳出二分循环,并返回 旋转点的值 nums[i]即可。

补充思考: 为什么本题二分法不用 nums[m]和 nums[i]作比较?
二分目的是判断 m在哪个排序数组中,从而缩小区间。而在 nums[m]>nums[i]情况下,无法判断 m在哪个排序数组中。本质上是由于 j初始值肯定在右排序数组中; i初始值无法确定在哪个排序数组中。举例如下:
对于以下两示例,当 i=0,j=4,m=2时,有 nums[m] > nums[i] ,而结果不同。
[1, 2, 3, 4 ,5]旋转点 x=0x = 0x=0 : m在右排序数组(此示例只有右排序数组);
[3,4,5,1,2] 旋转点 x=3x = 3x=3 : m在左排序数组。

参考面试题11. 旋转数组的最小数字(二分法,清晰图解)

class Solution {
public:
    int minArray(vector<int>& numbers) {
         int left=0;
         int right=numbers.size()-1;
         while(left<right){
             int mid=left+(right-left)/2;
             if(numbers[mid]>numbers[right]){
                 left=mid+1;
             }
             else if(numbers[mid]<numbers[right]){
                 right=mid;
             }
             else {
                 right=right-1;
             }
         }
         return numbers[left];
    }
};

参考

面试题11. 旋转数组的最小数字(二分法,清晰图解)
旋转数组的最小数字
三种情况,一次遍历

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值