【剑指Offer】旋转数组的最小元素——JavaScript实现

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。(牛客网题目)

分析

这道题可以很简单地遍历一次,即可得答案,时间复杂度为O(n),但是没有用到旋转数组的特性,结合旋转数组特性考虑,有以下几种情况:

1、按照NOTE,数组长度为0时,返回0;

2、数组长度为1时,返回这个唯一元素就好;

3、array[ 0 ] < array[ array.length - 1 ],说明 数组没有旋转,直接返回第一个元素

4、数组中没有重复元素,如题目中给的,数组经过旋转后,前后两段子数组都是有序的,可以用类似于二分查找的方法解决,一开始声明一个下标low指向第一个元素,high指向最后一个元素,取它俩中间数(坐标为middle)分别比较,若array[ middle ]大于 array[ low ],说明 array[ middle ]属于前一个子数组,则将middle赋给low;否则,若 array[ middle ]小于 array[ high ] ,说明 array[  middle ]属于后一个子数组,则将middle赋给high,如此循环,low最终将指向前一个子数组的最后一个元素(题目中数组元素5),high将指向后一个子数组的第一个元素(题目中的1),而high指向的这个元素就是最小元素。O( lgn )

5、数组中有重复元素,如{3,3,3,2,3},第一次循环low、middle、high指向的元素都相同,这时我们还是需要遍历low、与high之间的各数,找到最小元素。O( n )

代码如下:
function minNumberInRotateArray(rotateArray)
{
    // write code here
    if(rotateArray.length <= 1)return rotateArray.length <= 0 ? 0 : rotateArray[0];//情况1、2
    if(rotateArray[low] < rotateArray[high])return rotateArray[low];//情况3
    //正常情况(如题目中数组),或者有相等元素的数组
    var low = 0;
    var high = rotateArray.length - 1;
    var middle;
    while(high - low >= 1){
        if(high - low === 1){//当两个下标相邻时,high指向的就是最小元素
            break;
        }
        middle = parseInt((low + high) / 2);
        if(rotateArray[low] === rotateArray[middle] && rotateArray[middle] === rotateArray[high]){//情况5
            var result = rotateArray[low];
            for(var i=low;i<high;i++){
                if(rotateArray[i] > rotateArray[i+1])
                    result = rotateArray[i+1];
            }
            return result;
        }else if(rotateArray[low] <= rotateArray[middle])//中间值大于等于左边  {3,3,3,1,2}
            low = middle;
        else if(rotateArray[middle] <= rotateArray[high])//中间值小于等于右边  {3,3,1,1,1}
            high = middle;
    }
    return rotateArray[high];//情况4
}
值得一提的是,代码22行与24行一定不要落下“=”号,否则会漏掉部分情况,导致low与high无变化,从而进入死循环。具体示例数组见代码后的注释。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值