剑指offer-旋转数组的最小数字-JavaScript

题目

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

思路

  本题的直观解法很简单,直接对数组进行一次遍历就可以找到最小值,时间复杂度为O(n),但是显然这不是本题的意图所在,因为没有利用到任何旋转数组的特性。

       细想一下可以发现旋转之后的数组实际上可以划分为两个排序的子数组,而且前面排序的子数组的元素都大于或者等于后面子数组的元素,更重要的一点,最小的元素刚好是这两个子数组的分界线。在排序的数组中可以使用二分查找法,使用两个指针分别指向数组的第一个元素和最后一个元素。

  首先用两个指针low和high分别指向数组的第一个元素和最后一个元素,然后可以找到中间元素mid。对于这个中间元素,有以下两种情况:(1)该元素大于等于low指向的元素,此时最小的元素说明在mid的后面,可以把low=mid;(2)中间元素小于等于high指向的元素,那么最小元素在mid之前,可以high=mid。特别注意:这里不要+1或者-1,因为只有这样才能保证low始终在第一个数组,high始终在第二个数组。依次循环,当最后low和high相差1时,low指向第一个数组的最后一个,high指向第二个数组的第一个(即为我们要找的最小值)。以上查找的时间复杂度为O(logN)

  注意:虽然上面的分析包含了绝大多数的情况,但是仍然存在一种情况是我们并未考虑的,那就是第一个指针和第二个指针的值相等,并且中间位置的值也相等,这时候我们无法判断中间位置的值是属于第一个递增数组还是第二个递增数组,所以需要使用顺序查找来获取最小值。

 

一种特殊情况

JavaScript代码 

function minNumberInRotateArray(rotateArray)
{
  	var low = 0;
  	var high = rotateArray.length - 1;
  	var mid;
    if (rotateArray.length === 0) {
        return 0;
    } else {
        while (low < high) {
        	mid = Math.floor((high + low)/2);
          	if (rotateArray[low] === rotateArray[mid] && rotateArray[high] ===  rotateArray[mid]) {
            	return minInOrder(rotateArray);
            }
            if (high - low == 1) {
            	return rotateArray[high];
            }
            if (rotateArray[mid] > rotateArray[low]) {
            	low = mid;
            } else {
            	high = mid; 
            }
        }
    }
}

function minInOrder(arr) {
	var min = arr[0];
  	for(var i = 0; i < arr.length; i++) {
    	if (arr[i] < min) {
        	min = arr[i]; 
        }
    }
  	return min;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wangjun0708

你的打赏将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值