leetcode——旋转数组的最小数字

62 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情

前言

力扣练习第6天,拒绝思路老化。旋转数组的最小数字

题目信息如下:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2][1,2,3,4,5] 的一次旋转,该数组的最小值为 1。  

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]]

/**
 * @param {number[]} numbers
 * @return {number}
 */
/**
 * 输入: numbers = [3,4,5,1,2]
 * 输出: 1
 */

解法一

这种题,最简单的当然是不需要动脑的暴力法啦。一个一个比较过去输出最小的就OK啦。

var minArray = function(numbers) {
    let min = numbers[0];
    for(let i = 1; i < numbers.length; i++) {
        min = Math.min(min, numbers[i]);
    }
    
    return min
};

解法二

除了暴力法,当然还有方法啦,我们对数组进行排序然后输出最小的就好了嘛。

var minArray = function(numbers) {
    return numbers.sort((a, b) => a - b)[0];
};

解法三

仔细观察题目,给定的数组为一个有序数组的旋转数组,那么我们仔细观察旋转数组,发现是由两个有序的数组组成的。在这个特殊的结构中寻找最小的数,首选肯定是二分查找啦。

那么就有以下三种情况:

  • middle > right : 最小值在右半部分,left = middle
  • middle < right : 最小值在左半部分,right = middle
  • middle === right : 因为有重复元素,不能确定该值是需要的值,需要进一步缩小边界,right--
var minArray = function(numbers) {
    let left = 0,right = numbers.length - 1;
    while(left < right) {
        let middle = Math.floor((left + right) / 2);
        if(numbers[middle] > numbers[right]){
            left = middle + 1;
        }else if(numbers[middle] < numbers[right]){
            right = middle;
        }else{
            right--;
        }
    }
    return numbers[left];
};