持续创作,加速成长!这是我参与「掘金日新计划 · 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];
};