【剑指Offer】旋转数组的最小数字

1、题目描述

有一个长度为 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)

2、思路分析

如果直接暴力循环求解的话,是行不通的,那样的时间复杂度是O(n)。由原数组是非降序的,所以容易得知旋转后的数组是由两个非降序的子数组组成,左边的子数组的所有元素大于等于右边的子数组的元素,并且两个子数组的分界点就是数组的最小值。所以可以定义一个left=0,right=numsLen-1,当mid的值大于等于left的值时,说明最小值在mid的右边,此时把left放到mid的位置,缩小了范围,并且此时mid任在左边的子数组中。同样,当mid的值小于等于right的值时,说明最小值在mid的左边,此时把right放到mid的位置,缩小了范围,并且此时mid任在右边的子数组中。当left到左子数组的最后一个元素,right到右子数组的第一个元素时,即right-left==1时可以结束循环,此时right的值就是最小值。

此时要特别注意,题目中说的是将“若干个元素搬到数组的末尾”,所以可以是将0个元素搬到数组末尾,即不动数组此时直接将数组第一个值返回即可

【剑指Offer】旋转数组的最小数字_第1张图片

                                                                  left和right的图示

此时可以写出代码:

int minNumberInRotateArray(int* nums, int numsLen ) {
    int left = 0,right = numsLen-1,mid = 0;
    //如果说第一个元素小于最后一个元素,说明此时是将数组最开始的0个元素搬到数组末尾
    if(nums[left]=nums[right])
    {
        if(right-left==1)
            break;
        mid=(left+right)/2;
        if(nums[mid]>=nums[left]) left=mid;
        else if(nums[mid]<=nums[right]) right=mid;
    }
    return nums[right];
}

3、代码的修正

此时是根据前面的思路写出的代码,但它真的正确吗?

当数组是{0,1,1,1,1}的一个旋转数组{1,0,1,1,1}时根据上面的代码,可以得出的结果是1,很明显不正确。

【剑指Offer】旋转数组的最小数字_第2张图片

所以当left和right指向的数组元素的值相同时,需要遍历所有元素来查找,

于是得到最终代码:

int MinInOrder(int* nums,int left,int right)
 {
    int result = nums[left];
    for(int i = left+1;i<=right;i++)
    {
        if(result>nums[i]) result = nums[i];
    }
    return result;
 }
int minNumberInRotateArray(int* nums, int numsLen ) {
    int left = 0,right = numsLen-1,mid = 0;
    //如果说第一个元素小于最后一个元素,说明此时是将数组最开始的0个元素搬到数组末尾
    //所以直接返回第一个即可,注意此时不能有等于,如1,0,1,1,1
    if(nums[left]=nums[right])
    {
        if(right-left==1)
            break;
        mid=(left+right)/2;
        //若left,right,mid三者所指向的数相同,则只能顺序查找
        if(nums[left]==nums[mid]&&nums[mid]==nums[right])
            return MinInOrder(nums,left,right);
        if(nums[mid]>=nums[left]) left=mid;
        else if(nums[mid]<=nums[right]) right=mid;
    }
    return nums[right];
}

你可能感兴趣的:(算法,数据结构,leetcode,c语言)